Динамическое виртуальное поле cakephp или обратный вызов beforeFind

В настоящее время я присоединяю виртуальное поле в beforeFind() потому что мне нужно вставить идентификатор текущего пользователя в запрос. Вызов 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. Я не могу копировать виртуальные поля во время выполнения, как указано в кулинарной книге. Есть ли лучший обратный вызов для динамического присоединения виртуальных полей, чтобы они включались в результаты поиска?

1 ответ

Решение

Если речь идет только о включении виртуальных полей в результаты поиска, то вы можете, например, использовать отдельный метод, который их инициализирует, и вызывать этот метод из текущих запрашиваемых моделей. 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();
    }
}
Другие вопросы по тегам