我目前正在beforeFind()
附加一个虚拟字段,因为我需要将当前用户的id插入查询中。在相关模型上调用find并包含此模型包括静态定义的虚拟字段,但不包括beforeFind()
中的虚拟字段。直接在模型上调用find包括动态附加的虚拟字段。
这是我的beforeFind回调:
public function beforeFind($query = array()) {
$user_id = $this->getCurrentUser()['id'];
$this->virtualFields = array_merge($this->virtualFields, array(
'cost_for_user' => sprintf('CASE WHEN Inventory.user_id = %s THEN Inventory.cost ELSE Inventory.cost_for_team END', $user_id),
));
return $query;
}
由于cost_for_user
在beforeFind中动态附加,因此无法在cookbook中建议的情况下在运行时复制虚拟字段。动态附加虚拟字段是否有更好的回调,因此包含结果?
答案 0 :(得分:2)
如果它只是在查找结果中包含虚拟字段,那么您可以使用一个单独的方法来初始化它们,并从当前查询的模型beforeFind()
回调中调用此方法,如:
public function beforeFind($query = array())
{
if(!parent::beforeFind($query))
{
return false;
}
$this->RelatedModel->setupVirtualFields();
return true;
}
public function setupVirtualFields()
{
$user_id = $this->getCurrentUser()['id'];
$this->virtualFields = array_merge($this->virtualFields, array
(
'cost_for_user' => sprintf('CASE WHEN Inventory.user_id = %s THEN Inventory.cost ELSE Inventory.cost_for_team END', $user_id),
));
}
通过将其应用于所有模型和关联,例如在AppModel::beforeFind()
回调中或使用行为,您也可以使它更通用:
public function beforeFind($query)
{
if(!parent::beforeFind($query))
{
return false;
}
$this->_setupVirtualFields($this);
foreach(array_keys($this->getAssociated()) as $modelName)
{
$this->_setupVirtualFields($this->{$modelName});
}
return true;
}
protected function _setupVirtualFields(Model $model)
{
$method = 'setupVirtualFields';
if(method_exists($model, $method) && is_callable(array($model, $method)))
{
$model->setupVirtualFields();
}
}