更新Yii模型的(DRY)函数应存储在哪里


Where should the (DRY) function to update a Yii model be stored?

我有一个Yii应用程序,它有两个独立的模型,DomainPageDomain有一个唯一的字段,所以我设置了一个规则('domain', 'unique'),并创建了一个操作,如果字段是新的,则创建一个新记录,否则使用现有记录,并返回ID:

$domain_model=new Domain();
$domain_model->domain=$domain;
if(!$domain_model->save()){
    $atts = array('domain'=>$domain);
    $domain_model=Domain::model()->findByAttributes($atts);
}
return $domain_model->id;

这很好,但在Page控制器中,我想在页面插入操作期间调用相同的函数。我想不出用Yii做这件事的最佳DRY方法。我无法访问其他模型控制器,所以我不知道把这个函数放在哪里,以便在DomainMVC内外都可以访问它。

定义一个执行这些操作的行为,并将其附加到您想要使用的任何类。

组件行为的使用

组件支持mixin模式,并且可以附加一个或多个行为。行为是一个对象,其方法可以由其附加组件通过收集功能而不是专门化(即普通类继承)的方式"继承"。一个组件可以附加多个行为,从而实现"多重继承"。

行为类必须实现IBehavior接口。大多数行为都可以从CBehavior基类扩展而来。如果行为需要附加到模型,它也可以从CModelBehavior或CActiveRecordBehavior扩展,后者实现了特定于模型的附加功能。

要使用行为,必须首先通过调用行为的attach()方法将其附加到组件。然后我们可以通过组件调用一个行为方法:

// $name uniquely identifies the behavior in the component
$component->attachBehavior($name,$behavior);
// test() is a method of $behavior
$component->test();

附着的行为可以像组件的正常属性一样进行访问。例如,如果一个名为树的行为被附加到一个组件上,我们可以使用获得对该行为对象的引用

$behavior=$component->tree;
// equivalent to the following:
// $behavior=$component->asa('tree');

可以暂时禁用行为,从而使其方法无法通过组件使用。例如,

$component->disableBehavior($name);
// the following statement will throw an exception
$component->test();
$component->enableBehavior($name);
// it works now
$component->test();

附加到同一组件的两个行为可能具有相同名称的方法。在这种情况下,第一个附加行为的方法将优先。

当与事件一起使用时,行为会更加强大。行为在附加到组件时,可以将其某些方法附加到组件的某些事件。通过这样做,行为有机会观察或更改组件的正常执行流。

行为的属性也可以通过它所连接的组件访问。这些属性包括公共成员变量和通过行为的getter和/或setter定义的属性。例如,如果行为具有名为xyz的属性,并且该行为附加到组件$a。然后我们可以使用表达式$a->xyz来访问行为的属性。

更多阅读:
http://www.yiiframework.com/wiki/44/behaviors-events
http://www.ramirezcobos.com/2010/11/19/how-to-create-a-yii-behavior/

我记不清Yii了,但我相信有一个"beforeSave"回调可以用于Domain模型。不管怎样,当你保存一个域模型时,它总是会调用"在保存模型之前检查这个id是否已经存在"

然后,您只需执行$domain->save();,然后执行$domain->id,不管它以前是否存在。