views:

179

answers:

1

In my CakePHP 1.2.5 app, I have a Profile model that belongsTo a User model. The User model has a username field, and when performing a find() on the Profile model, I want to always automatically retrieve the value of User.username too. I figure it would make sense to modify my Profile model's beforeFind() method to automatically contain the desired field.

Here's what I attempted to do:

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

I can see that the value of $queryData['contain'] is properly being updated, but the username data isn't being retrieved. I looked into the CakePHP core code for the find() method, and I found that the beforeFind() callback is being called after all Behaviors' callbacks, meaning that Containable already did what it needed to do with the value of $queryData['contain'] before I was able to modify it.

How can I work around this without hacking the core?

+2  A: 

I solved it, so here's my answer in case anyone has the same complication. Containable fields cannot be specified in beforeFind since all Behaviors' beforeFind() methods are called prior to the model's beforeFind() method.

As such, it was necessary for me to modify the find() method directly on the Profile model in order to append my custom containable field.

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);
}
Matt Huggins
Thanks! I was puzzling over this too, wondering if the beforeFind() modification was "too late". Indeed, it was.
Wayne Khan