cakephp dynamic virtualfield或使用containable在查找回调之前应用

cakephp dynamic virtualfield或使用containable在查找回调之前应用,php,cakephp,containable,cakephp-2.4,Php,Cakephp,Containable,Cakephp 2.4,我当前正在beforeFind()中附加一个虚拟字段,因为我需要在查询中插入当前用户的id。在相关模型上调用find并包含此模型包括静态定义的虚拟字段,但不包括beforeFind()中的虚拟字段。。直接在模型上调用find包括动态附加的虚拟字段 以下是我的beforeFind回调: public function beforeFind($query = array()) { $user_id = $this->getCurrentUser()['id']; $this-&

我当前正在
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\u
动态附加在beforeFind中,因此我无法在运行时使用中建议的类似项复制虚拟字段。动态附加虚拟字段以便包含在包含结果中是否有更好的回调?

如果只是在查找结果中包含虚拟字段,那么您可以使用单独的方法对其进行初始化,并从当前查询的模型中调用此方法
beforeFind()
回调,类似于:

public function beforeFind($query = array())
{
    if(!parent::beforeFind($query))
    {
        return false;
    }

    $this->RelatedModel->setupVirtualFields();
    return true;
}
您还可以将其应用于所有模型和关联,例如在
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();
    }
}

这非常有效,谢谢。。不过有几个问题。beforeFind()不应该返回$query吗?从AppModel检查parent::beforeFind($query)有什么意义?@DevinCrossman不客气
Model::beforeFind()
需要返回
$query
,只有在修改了
$query
并且实际应该使用这些修改的情况下,返回
true
意味着继续原始查询数据。在大多数情况下,
AppModel
上不需要调用
parent::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();
    }
}