We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Model Method for before find*

Is there a method I can hook into that allows me to perform actions on the model before it is returned by the likes of the find commands, much like there is a beforeSave() command?

Not beforeCreate or beforeUpdate, but when retrieveing these objects from the store, I want to perform an action.



9.3k
edited Apr '14

you can extends phalcon\mvc\model, and overwrite the method such like that

    pubilic static function findFirst($parameters=null)
    {
        $this->beforeFindFirst($parameters);
        return parent::findFirst($parameters);
    }

    public function beforeFindFirst($parameters)
    {
        // your code
    }
edited Apr '14

Thanks for that information, Barbery. I took a look a stab at it this morning and came up with the below.

I did neglect to mention that I was using Mongodb backend, and thus using \Phalcon\Mvc\Collection. After playing around this morning, I found that I can leverage writeAttribute.

I am doing this so as to make it much simipler to have related models in the system. See below for what I am doing. Feel free to comment if you have a better solution.

Base Model

    public function beforeSave()
    {
        foreach ($this as $key => $value) {
            if (substr($key, 0, 1) == "_") {
                continue;
            }

            if (is_subclass_of($value, __CLASS__)) {
                $value->save();
                $ref = array(
                    'referencedClass' => $value->getSource(),
                    'id' => $value->getId()
                );
                $this->$key = $ref;
            }
        }
    }

    public function writeAttribute($name, $value)
    {
        if (is_array($value) && array_key_exists('referencedClass', $value) && array_key_exists('id', $value) &&
            $value['id'] instanceof \MongoId) {

            $className = preg_replace("/_/", '\\', $value['referencedClass']);

            $oldValue = $value;

            $value = call_user_func_array(
                $className . '::findFirst',
                array(array(
                    '_id' => $value['id']
                ))
            );
        }

        return parent::writeAttribute($name, $value);
    }

Example usage:

        $user = new \Netadmin\Main\Model\User();
        $user->fName = "First";
        $user->lName = "Last";

        $role = new \Netadmin\Main\Model\Role();
        $role->role = "Admin";
        $user->role = $role;
        $user->save();

So, the Role object will be saved into its own collection, and when the user is pulled from the db, thie base model will automatically load that model into the value, reducing duplication.



7.2k

Do you mean afterFetch?

class Robots extends Phalcon\Mvc\Model
{

    public $id;

    public $name;

    public $status;

    public function afterFetch()
    {
        //Convert the string to an array
        $this->status = explode(',', $this->status);
    }
}

jhtan1 - Is there a distinct advantage of one over the other? writeAttribute() is called whenever an object is populated after/during fetching.



7.2k

Trenton Craig, I'm not sure for the writeAttribute(). Kindly go through Initializing/Preparing fetched records for afterFetch()