Yii 通过 SOAP 为其服务 AR 及其相关性()
我的问题:
通过@soap公开具有relations()的AR最明智的方式是什么?是否可以公开相关的 AR,而无需手动将其分配给公共 @soap 成员?是否可以以某种方式将关系()中定义的关系名称与@soap变量链接起来?
这是我正在做的事情的详细背景。我实际上成功地将 AR 记录与其相关的 AR 记录共享,但我认为这很混乱,想问是否有人知道更优雅的方法。
背景:
我已经成功通过soap公开了AR记录,方法是添加用@soap注释的公共变量:
在属性模型中:
/** @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 记录作为请求的一部分(想要添加状态详细信息,所以首先我在状态模型的属性模型中添加关系表达式:
/**
* @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
这有点混乱,因为:
- 需要始终执行此 $model->_STATE 分配,
- 同时拥有名为 STATE 的相关 AR 和公共 @soap 变量 $ 是多余的_STATE 持有基本相同的信息
有什么想法吗?
谢谢!
MY QUESTION:
What is the smartest way to expose through @soap a AR that has relations()? Is it possible to expose the related AR without manually assigning it to a public @soap member? Is it possible to link the relation name defined in the relations() with the @soap variable in some way?
Here is a looong background on what i was doing. I actually successfully shared the AR record with it's related AR records, but i think this is messy and want to ask if someone knows a more elegant way.
BACKGROUND:
I've successfully expose a AR record through soap by adding public variables annotated with @soap:
In Property Model :
/** @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;
This works ok!
The next thing i want is to send the a related AR record as part of the request (want to add the state details, so first of all i added the relation expression in the Property model for the States model:
/**
* @return array relational rules.
*/
public function relations()
{
return array('STATE' => array(self::BELONGS_TO, 'State', 'fk_state'), );
}
... add @soap variables to the State model too:
/** @soap @var integer */ public $id;
/** @soap @var string */ public $title;
/** @soap @var integer */ public $code;
Now i add a @soap public variable to the Property model to hold the related AR object:
/** @soap @var State */ public $_STATE;
this means that i want to send an object of type State through SOAP.
The last thing, before serving the data is to assign the related AR record of the STATE to the public @soap variable $_STATE:
$model->_STATE = State::model()->STATE; // assign related AR object to to the public @soap variable
It's kind of messy because:
- need to do this $model->_STATE assignment all the time
- it's redundant to have both the related AR called STATE and the public @soap variable $_STATE that hold basically the same info
Any ideas?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为这个重复的步骤创建一个行为怎么样?
那么重写 __get 魔术方法来自动服务状态怎么样?
How about creating a Behavior for this repeated steps?
And what about overwriting __get magic method to serve the state automatically?
我也觉得这很烦人。
CWsdlGenerator 使用反射,并且专门仅查找定义的公共属性,因此它不会找到像关系这样的神奇属性。您必须将它们声明为公开的。
但 CActiveRecord 使用神奇的 __get() 函数来加载关系。并且 __get() 不会为现有的公共属性调用,因此如果您声明它们,那么它们将永远不会被加载。您始终必须使用 $model->STATE = $model->getRelated('STATE') 显式加载它们。
我想到子类化 CWsdlGenerator 并重写 processType() 来检查一些新的文档注释,以允许您显式声明魔术属性;但 processType() 是私有的,因此不能被覆盖。
CWebServiceAction 可以被子类化,并且您可以重写 createWebService() 以将 CWebService->generatorConfig 设置为使用不同的类而不是 CWsdlGenerator。我创建了一个名为 CWsdlGeneratorMagic 的副本,并添加了 10 行来解析文档注释。我不喜欢它作为解决方案,但它可以工作。
在我的模型的类文档注释中(这些声明了 HAS_MANY 关系“图片”和“源”的神奇属性):
在我的控制器类中:
在 CWebServiceActionMagic.php 中:
在 CWsdlGeneratorMagic 中(在 processType() 的末尾,就在关闭之后foreach($class->getProperties() as $property)) 的大括号:
我认为应该可以设置CWebService 的生成器配置在应用程序配置文件中,这样您就不需要 CWebServiceActionMagic,但我无法让它工作。
@magic 声明基本上与 @property 声明相呼应,但仅适用于我想要在 WSDL 中公开的声明。 (可能应该将其称为@soapmagic 或其他名称)。
I find this irritating as well.
CWsdlGenerator uses reflection and specifically looks only for defined public properties, so it won't find magic properties like the relations. You have to declare them as public.
But CActiveRecord uses the magic __get() function to load the relations. And __get() isn't called for an existing public property, so if you do declare them, then they will never get loaded. You would always have to explicitly load them using $model->STATE = $model->getRelated('STATE').
I thought of subclassing CWsdlGenerator and overriding processType() to check for some new doc comment to allow you to explicitly declare magic properties; but processType() is private so can't be overridden.
CWebServiceAction can be subclassed, and there you can override createWebService() to set the CWebService->generatorConfig to use a different class instead of CWsdlGenerator. I created a copy called CWsdlGeneratorMagic and added 10 lines to parse out the doc comment. I don't like it as a solution, but it could work.
Within my model's class doc comment (these declare the magic properties of the HAS_MANY relations 'pictures' and 'sources'):
Within my controller class:
within CWebServiceActionMagic.php:
within CWsdlGeneratorMagic (at the end of processType(), just after the closing brace of foreach($class->getProperties() as $property)):
I think that it should be possible to set CWebService's generatorConfig in the application configuration file so that you wouldn't need CWebServiceActionMagic, but I couldn't get it to work.
The @magic declarations basically echo the @property ones, but only for the ones that I want exposed in the WSDL. (Should probably call it @soapmagic or something instead).