Как определить minOccurs и maxOccurs в функции phpDoc для Zend_Soap_Server?
Я использую Zend_Soap_Server для создания веб-сервиса, использующего режим автообнаружения в PHP, и мне было интересно, как генерировать ограничения (minOccurs, maxOccurs) для конкретного параметра переменной / функции, используя phpDoc или любым другим способом.
Например, когда я использую этот phpDoc над функцией myFunction
,
/**
*
* @param string $param1 Parameter One
* @param string $param2 Parameter Two
* @return array $return
*/
это дает мне следующее сообщение в WSDL:
<message name="myFunctionIn">
<part name="param1" type="xsd:string"/>
<part name="param2" type="xsd:string"/>
</message>
<message name="myFunctionOut">
<part name="return" type="soap-enc:Array"/>
</message>
Так что если я хочу ограничить функцию params (param1
& param2
) с помощью minOccurs
а также maxOccurs
Как я могу сделать это, чтобы сообщение WSDL было так:
<message name="myFunctionIn">
<part name="param1" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<part name="param2" minOccurs="1" maxOccurs="1" type="xsd:string"/>
</message>
Я искал по интернету, но не смог найти никакой полезной информации. Спасибо!
4 ответа
В случае, если некоторые люди все еще заинтересованы... есть довольно простой патч, размещенный в списке рассылки Zend Framework здесь. Это позволяет определять minOccurs и maxOccurs в следующем стиле:
/**
* @var string ___FOR_ZEND_minOccurs=0 ___FOR_ZEND_maxOccurs=1
*/
public $Username;
который переводится в WSDL на:
<xsd:element name="Username" type="xsd:string" nillable="true" maxOccurs="1" minOccurs="0"/>
Необходимые изменения кода необходимо вставить после строки 58, которая выглядит следующим образом:
($element->setAttribute('type', $this->getContext()->getType(trim($matches[1][0])));)
код для вставки:
$tempo = $property->getDocComment();
if (preg_match('/___FOR_ZEND_minOccurs\s*=\s*(\d+|unbounded)/',$tempo,$matches)) {
$element->setAttribute('minOccurs', $matches[1]);
}
if (preg_match('/___FOR_ZEND_maxOccurs\s*=\s*(\d+|unbounded)/',$tempo,$matches)) {
$element->setAttribute('maxOccurs', $matches[1]);
}
Очевидно, что вы можете адаптировать эти регулярные выражения, если вы предпочитаете другой шаблон для ваших определений.
В случае, если это все еще актуально для кого-то: более чистый подход может заключаться в реализации пользовательского класса стратегии для построения определений сложных типов - что-то, что фактически официально поддерживается Zend_Soap.
Сделайте это, создайте класс, который унаследован от Zend_Soap_Wsdl_Strategy_ArrayOfTypeSequence (ссылается на ZF 1.x, но выглядит в более новых версиях фреймворка похожим, только с пространством имен).
В вашем новом классе перегрузите метод _addElementFromWsdlAndChildTypes, скопировав все тело метода из родительского класса.
Теперь вы можете начать манипулировать кодом и добавлять анализатор докблока, создав объект отражения для заданного $ childTypeName:
// add the following after
// $element = $dom->createElement('xsd:element');
$strippedTypeName = substr($childTypeName, 4); // strip xml namespace
$reflect = new \Zend_Reflection_Class($strippedTypeName);
if ($reflect->getDocblock()->hasTag('myTagName')) {
$tagValues = $reflect->getDocblock()->getTags('myTagName');
// do whatever you want with your attribute values and then
// add them to the XML element:
$element->setAttribute($attributeName, $attributeValue);
}
Когда вы закончите, вы можете установить новый класс в качестве стратегии типа при создании экземпляра AutoDiscover:
new Zend_Soap_AutoDiscover(
'MyNewStrategyClass', $namespace
);
И вы сделали. Теперь, когда у вас есть класс, определяющий сложный тип, который должен иметь пользовательские параметры minOccurs, maxOccurs или любые другие параметры, вы можете аннотировать класс с помощью тегов @myTagName и любого синтаксиса, который вам нравится, чтобы определить значения атрибутов, например
/**
* MyCustomType DocBlock description
* @myTagName minOccurs=0
* @myTagName maxOccurs=10
*/
class MyCustomType { ... }
Надеюсь, это кому-нибудь поможет.
Есть предложение, которое я нашел, включая модифицированный код для сложных типов, но я не уверен, был ли он когда-либо реализован, и у меня еще не было возможности протестировать его. Проверять, выписываться:
Я искал ответ на это во время недавнего проекта. Насколько я знаю, это невозможно в текущей версии ZF (см. " Ошибка").
Я думаю, что AutoDiscovery предназначен только для самого базового поколения WSDL. Или, по крайней мере, текущая версия. Возможно, будущие выпуски будут более полными.
Это отличная отправная точка, которую вы можете использовать для создания более сложных ограничений вручную. Кроме того, вы можете создать свой собственный класс для удовлетворения ваших конкретных требований (как это предлагается в комментариях к ответу на этот вопрос)