2009-10-19 1 views
3

В моем приложении CakePHP 1.2.5 у меня есть модель Profile, которая принадлежит модели User. Модель пользователя имеет поле username, а при выполнении find() в модели профиля я хочу всегда автоматически получать значение User.username. Я полагаю, что имеет смысл модифицировать метод модели beforeFind() модели профиля, чтобы автоматически содержать нужное поле.Изменение допустимых полей, требуемых для обратного вызова beforeFind?

Вот что я пытался сделать:

public function beforeFind($queryData) { 
    // determine if the username data was already requested to be included in the return data via 'User.username' or 'User' => array('username'). 
    $hasUserData = isset($queryData['contain']) && in_array("User.{$this->User->displayField}", $queryData['contain']); 
    $hasUserData |= isset($queryData['contain']['User']) && in_array($this->User->displayField, $queryData['contain']['User']); 

    // request the the username data be included if it hasn't already been requested by the calling method 
    if (!$hasUserData) { 
     $queryData['contain']['User'][] = $this->User->displayField; 
    } 

    return $queryData; 
} 

Я могу видеть, что значение $queryData['contain'] правильно обновляется, но данные имени пользователя не будет получен. Я просмотрел основной код CakePHP для метода find(), и я обнаружил, что обратный вызов beforeFind() вызывается после всех обратных вызовов Behaviors, что означает, что Containable уже сделал то, что ему нужно было сделать со значением $queryData['contain'], прежде чем я смог его изменить ,

Как я могу обойти это без взлома ядра?

ответ

6

Я решил это, так что вот мой ответ на тот случай, если у кого-то будет такое же усложнение. Контейнерные поля не могут быть указаны в beforeFind, поскольку все методы Behaviors beforeFind() называются до до метода модели beforeFind().

Как таковой, мне необходимо было изменить метод find() непосредственно на модели профиля, чтобы добавить мое настраиваемое поле для сдерживания.

public function find($conditions = null, $fields = array(), $order = null, $recursive = null) { 
    $this->contain("{$this->User->alias}.{$this->User->displayField}"); 
    return parent::find($conditions, $fields, $order, $recursive); 
} 
+0

Спасибо! Я тоже задумывался над этим, задаваясь вопросом, была ли модификация beforeFind() «слишком поздней». Действительно, это было так. – Wayne

1

Мэтт, я считаю, что это прекрасное решение. Я использую CakePHP 2.0.4, и я собирался извлечь только данные модели пользователя.

Просто для записи, установка actsAs для модели пользователя

class User extends AppModel { 
    public $name = 'User'; 
    public $belongsTo = array('Role'); 
    public $actsAs = array('Containable'); 
    ... 

Тогда я переопределить метод найти этот путь:

public function find($conditions = null, $fields = array(), $order = null, $recursive = null) { 
    $this->contain(); 
    return parent::find($conditions, $fields, $order, $recursive); 
} 

Или, собираясь принести профиля данных, например:

public function find($conditions = null, $fields = array(), $order = null, $recursive = null) { 
    $this->contain(array('Profile')); 
    return parent::find($conditions, $fields, $order, $recursive); 
} 
Смежные вопросы