1

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;
}

beforeFind に動的にアタッチされているため、クックブックcost_for_userで提案されているように、実行時に仮想フィールドをコピーすることはできません。仮想フィールドを動的にアタッチするためのより良いコールバックはありますか?

4

1 に答える 1

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();
    }
}
于 2013-10-19T10:50:28.157 に答える