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

Custom Phalcon\Mvc\Model\Row class?

I've noticed that when you use Model::find() you get a resultset class instance containing instances of Model as the rows.

This is nice because if we wanted to have a custom method in Model that for example returned a user's full name, we could do this easily and then call it from our view as a kind of virtual field. Simple example:

Model:

// inside my Users.php model, which has fields for first_name and last_name in the schema
public function getFullname() {
    return $this->first_name . ' ' . $this->last_name;
}

View (volt):

{% for user in users %}
    {{ user.id }}: {{ user.getFullName() }} 
{% endfor %}

The problem is that if you do anything more complicated, i.e. with Query Builder, the class that is returned for each row becomes Phalcon\Mvc\Model\Row. So we've lost the ability to access our getFullName() method in our Users model.

Looking at the source, it doesn't seem possible to override the use of Phalcon\Mvc\Model\Row?

I noticed that for the the class of the resultset, you can define a special method in your model class called getResultsetClass() which allows you to use a custom resultset class. It would be so great if we could also do this for the row class too! I don't want to change the default Model::find() behaviour but it would be nice to have more control for more complex queries.

You could then have traits that are shared between the custom row class and your model class which could house the getFullName() method, to keep things DRY.

What do you all think?

Please let me know if this is already possible, but I've had a good read through the docs and I couldn't see anything.

You may have already realized/discovered this, but if your complex query just asks for everything from a single table, then the result will be models.

Basically, querying for just User.* will return a bunch of User models. Querying for User.first_name,BillingCycle.period or User.first_name, User.hometown (for example) will return Rows.

I suppose you could also create a method that hydrates a resultset of Rows into User objects. It shouldn't be too hard to make it generic.