2011-12-01 45 views
1

我的问题:Yii的服务AR与它的通过SOAP关系()

什么是通过@soap暴露有关系AR()最聪明的方法是什么?是否可以公开相关的AR,而无需手动将其分配给public @soap成员?是否有可能以某种方式将关系()中定义的关系名称与@soap变量链接起来?

这是关于我在做什么的looong背景。我实际上已经成功地将AR记录与其相关的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; 

该工程确定

我已经成功地通过添加具有@soap注释公共变量暴露出AR记录通过SOAP!

我想接下来的事情就是发送一个相关的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公共变量添加到属性模型来保存相关的AR对象:

/** @soap @var State */ public $_STATE; 

这意味着我想通过SOAP发送一个类型为State的对象。

的最后一件事,之前服务的数据是对国家有关AR记录分配给公众@soap变量$ _STATE:

$model->_STATE = State::model()->STATE; // assign related AR object to to the public @soap variable 

这是一种混乱的原因是:

  1. 需要这样做$ model - > _ STATE分配所有的时间
  2. 它是冗余的,既有相关的AR称为状态和public @soap变量$ _STATE基本上保持相同fo

任何想法?

谢谢!

回答

0

如何为此重复步骤创建行为?

那么覆盖__get魔术方法自动为状态服务呢?

+0

你可以开发你的想法? – paladin

0

我觉得这也很刺激。

CWsdlGenerator使用反射,特别是只查看定义的公共属性,所以它不会找到像关系那样的神奇属性。你必须宣布它们是公开的。

不过的CActiveRecord使用魔法__get()函数加载关系。和__get()不要求现有的公共属性,所以如果你声明它们,那么他们将永远不会被加载。你总是有他们使用$基于模型显式地加载> STATE = $模型 - > getRelated(“状态”)。

我想继承CWsdlGenerator和压倒一切的processType()来检查一些新的文档注释,让您可以显式声明魔法属性的;但processType()是私有的,所以不能被覆盖。

CWebServiceAction可以被子类化,在那里你可以重写createWebService()来设置CWebService-> generatorConfig使用不同的类而不是CWsdlGenerator。我创建了一个名为CWsdlGeneratorMagic的副本,并添加了10行来解析文档评论。我不喜欢它作为解决方案,但它可以工作。

在我的模型类的文档注释(这些声明HAS_MANY关系 '图片' 和 '源' 的魔法属性):

/** 
* 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类型(),刚刚的foreach(如$属性类 - $>的GetProperties()))的右括号后:

// 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或者其他)。