Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NFR] ORM: add the ability to return a custom Phalcon\Mvc\Model\Row class instance #13587

Open
richmilns opened this issue Nov 8, 2018 · 4 comments

Comments

Projects
None yet
3 participants
@richmilns
Copy link

commented Nov 8, 2018

Overview

Similar to issue #12166 it would be great if this could be taken a step further so that a custom Phalcon\Mvc\Model\Row can be returned when using Query Builder for more complex queries.

See original post on forum.

Reason for NFR & Example Usage / Syntax

At the moment, if you use Model::find() methods and don't specify columns you are returned an instance of Model. If you use joins and/or custom columns, the class of each row becomes Phalcon\Mvc\Model\Row. If we could override this class, it would be possible to have re-usable utility methods to keep things DRY that would be usable in your View, Controller etc.

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

Suggested Syntax

In your model class, similar to #12166:

namespace Models;
class Users extends \Phalcon\Mvc\Model {
    public $id;
    public $first_name;
    public $last_name;

    public function getResultsetRowClass() {
        return 'Resultsets\Row\User';
    }
}
namespace Resultsets\Row;
class User extends Phalcon\Mvc\Model\Row {
    public function getFullName() {
        return sprintf('%s %s', $this->first_name, $this->last_name);
    }
}

You could even put the getFullName() method in a trait so that the logic can be included in your model as well to keep things DRY.

Then in your view you could do something like:

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

An alternative would be to add this when you're executing a built query:

$data = $queryBuilder->getQuery()->setResultsetRowClass('Resultsets\Row\User')->execute();

I'm by no means an expert but I think this might be more straight forward than adding to the model actually. We could have setResultsetRowClass / getResultsetRowClass methods added into Phalcon\Mvc\Model\Query which would be used on line 2816:

let resultObjectClass = this->getResultsetRowClass();
let resultObject = new {resultObjectClass}();

Details

  • Phalcon version: 3.4.0
  • PHP Version: 7.2.11
  • Operating System: macOS
  • Installation type: HomeBrew
  • Zephir version (if any): n/a
  • Server: Apache
  • Other related info (Database, table schema): MySQL 5.7

@richmilns richmilns changed the title [NFR] ORM: add the ability to set a custom Phalcon\Mvc\Model\Row class in your model [NFR] ORM: add the ability to return a custom Phalcon\Mvc\Model\Row class instance Nov 8, 2018

@Jurigag

This comment has been minimized.

Copy link
Member

commented Nov 8, 2018

Well i really like this idea, we could even for example create like Entity class without any extends or something which would have all necessary methods, and extend it both in our model class and row class, so we could still have all needed methods(though this could be achieved already therotically with magic __call.

richmilns pushed a commit to richmilns/cphalcon that referenced this issue Dec 1, 2018

@richmilns

This comment has been minimized.

Copy link
Author

commented Dec 1, 2018

I've had a go at adding this functionality - it's my first time using Zephir but I was able to test this and it seems to be working as outlined above.

I added get/set methods for the Resultset Row Class.

@richmilns

This comment has been minimized.

Copy link
Author

commented Dec 3, 2018

I just saw the announcement about 3.4.2 being the last release for 3.x. My code above was based on the 3.4.x branch of Phalcon, so I guess it might be in the wrong place! Please advise if this needs to be refactored on the 4.0.x branch instead, and if you'd like this submitted as a pull request?

@stale stale bot added the stale label Mar 3, 2019

@stale stale bot closed this Mar 4, 2019

@phalcon phalcon deleted a comment from stale bot Mar 5, 2019

@niden niden reopened this Mar 5, 2019

@stale stale bot removed the stale label Mar 5, 2019

@Jurigag

This comment has been minimized.

Copy link
Member

commented May 15, 2019

I think we should consider this more to have better compability with php 7.2 features, what i mean:

interface Xyz
{
    public function getName();
}
class RowXyz extends Phalcon\Mvc\Mode\Row implements Xyz
{
    public $name;

    public function getName()
    {
        return $this->name;
    }
}
class ModelXyz extends Phalcon\Mvc\Model implements Xyz
{
    protected $name;

    public function getName()
    {
        return $this->name;
    }
}

And then somewhere we could have code like:

class XyzRepository
{
    public function findByParams(array $params) : ?Xyz
    {
        // we create somewhere $arrayParams which can have or not columns property
        return ModelXyz::findFirst($arrayParams);
    }
}

Also i would even vote for adding posibility that it doesn't needs to extend Row object, it's already simple object just having some additional methods, maybe just implementing some interface could be enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.