我的问题:
通过@soap公开具有关系()的AR的最明智的方法是什么?是否可以公开相关的AR而无需手动将其分配给公共@soap成员?是否可以以某种方式将relations()中定义的关系名称与@soap变量链接起来?
这是我正在做的事情的背景。我实际上成功地用它的相关AR记录共享了AR记录,但我觉得这很麻烦,想问一下是否有人知道更优雅的方式。
背景
我通过添加使用@soap注释的公共变量
成功地通过soap公开了AR记录在物业模型中:
/** @soap @var integer */ public $id;
/** @soap @var string */ public $street;
/** @soap @var string */ public $city;
/** @soap @var integer */ public $fk_state;
/** @soap @var string */ public $property_title;
这样可行!
我想要的下一件事是发送相关的AR记录作为请求的一部分(想要添加状态细节,所以首先我在States模型的Property模型中添加了关系表达式:
/**
* @return array relational rules.
*/
public function relations()
{
return array('STATE' => array(self::BELONGS_TO, 'State', 'fk_state'), );
}
...也将@soap变量添加到State模型中:
/** @soap @var integer */ public $id;
/** @soap @var string */ public $title;
/** @soap @var integer */ public $code;
现在我将一个@soap公共变量添加到Property模型中以保存相关的AR对象:
/** @soap @var State */ public $_STATE;
这意味着我想通过SOAP发送State类型的对象。
在提供数据之前,最后一件事是将STATE的相关AR记录分配给公共@soap变量$ _STATE:
$model->_STATE = State::model()->STATE; // assign related AR object to to the public @soap variable
这有点乱,因为:
有什么想法吗?
谢谢!
答案 0 :(得分:0)
如何为这些重复步骤创建行为?
如果要覆盖__get魔术方法来自动提供状态呢?
答案 1 :(得分:0)
我也觉得这很刺激。
CWsdlGenerator使用反射并专门查找已定义的公共属性,因此它不会找到像关系这样的魔术属性。你必须将它们声明为公开。
但是CActiveRecord使用魔术__get()函数来加载关系。并且没有为现有公共属性调用__get(),因此如果执行声明它们,那么它们将永远不会被加载。你总是必须使用$ model-> STATE = $ model-> getRelated('STATE')显式加载它们。
我想到了继承CWsdlGenerator并重写processType()以检查一些新的doc注释,以允许你显式声明魔术属性;但processType()是私有的,因此无法覆盖。
CWebServiceAction可以是子类,您可以在其中覆盖createWebService()以将CWebService-> generatorConfig设置为使用不同的类而不是CWsdlGenerator。我创建了一个名为CWsdlGeneratorMagic的副本,并添加了10行来解析doc注释。我不喜欢它作为解决方案,但它可以工作。
在我的模型的类doc注释中(这些声明了HAS_MANY关系'pictures'和'sources'的神奇属性):
/**
* The following is for the SOAP WSDL generator replacement CWsdlGeneratorMagic
* @magic Picture[] $pictures
* @magic Source[] $sources
*/
在我的控制器类中:
/**
* Make this a webservice
*/
public function actions() {
return array(
'api'=>array(
'class'=>'CWebServiceActionMagic',
),
);
}
在CWebServiceActionMagic.php中:
protected function createWebService($provider,$wsdlUrl,$serviceUrl)
{
$a = new CWebService($provider,$wsdlUrl,$serviceUrl);
$a->generatorConfig = 'CWsdlGeneratorMagic';
return $a;
}
在CWsdlGeneratorMagic中(在processType()的末尾,就在foreach的结束括号之后($ class-> getProperties()为$ property)):
// Handle magic properties
$comment = $class->getDocComment();
$matches = array();
if (preg_match_all('/@magic\s+([\w\.]+(\[\s*\])?)\s*?(.*)$/mi', $comment, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
$name = trim($match[3]);
$name = ltrim($name, '$');
$this->_types[$type][$name]=array($this->processType($match[1]),trim($match[3])); // name => type, doc
}
}
// end handling of magic properties
return 'tns:'.$type;
我认为应该可以在应用程序配置文件中设置CWebService的generatorConfig,这样就不需要CWebServiceActionMagic了,但是我无法让它工作。
@magic声明基本上回应了@property声明,但仅限于我希望在WSDL中公开的声明。 (应该把它称为@soapmagic或者其他东西)。