Subclassing results of a phql query

Hello,

i have a phql piece like the one below:

$result = $this->di['modelsManager']->createBuilder()
            ->addFrom('MyModel', 'm')
            ->columns(['*'])
            ->getQuery()
            ->execute();

Let's assume i have subclasses MyModelA and MyModelB

Is there a way to hijack ->execute() to use a factory that would generate my subclasses and return a ResultSet\Complex with those ?

Thanks :)

You can use an array in from method but you get a ResultSet\Simple. You get Complex when use ie a sum() function in columns

$result = $this->di['modelsManager']->createBuilder() ->from([
    'm' => 'MyModel',
    'm2' => 'ModelTwo',
]) ->columns(['*']) ->getQuery() ->execute();

Good luck

I believe that would return a ResultSet\Simple currently. What do you need a Complex for?

Oops, yes...it's a resultset\simple.

It seems i haven't made myself very clear...

so, this resultSet will contain an array of

MyModel instances

what i want is for it to contain

MyModelA MyModelB MyModelA MyModelC etc

I know i can override the 'find' and 'findFirst' methods of models, but for cases where i use the query builder...how can this be achieved

Thanks.

Oh, I see. Well to do that I think you'd have to write your own class that extends Phalcon\Mvc\Model\Query\Builder::execute() to loop through the results parent::execute generates and instantiate sub-classes. Personally though, I'd just create a function to do this - no need to overload the QueryBuilder.

I have to ask though, why do you have multiple model classes that point to the same table?

edited 29d ago

Yep, that's what i went for: i have some dbProvider classes that return query builder results (with joins, groupBy, etc) and each call an output method that instantiates accordingly. Something along the lines of:

class BaseDbProvider extends \Phalcon\Mvc\User\Component
{
    protected $di;

    public function __construct(){
        $this->di = \Phalcon\DI::getDefault(); // or pass the DI as a constructor argument
    }
    protected function output($result){
        if ($result instanceof Phalcon\Mvc\Model\Resultset\Complex){
            $resultArray = [];
            foreach ($result as $k => $r){
                $obj = new stdClass();
                foreach ($r as $kobj => $vobj){
                    if ($vobj instanceof UserExt){
                        $obj->{$kobj} = UserFactory::create($vobj->type, $vobj->toArray());
                        continue;
                    }
                    $obj->{$kobj} = $vobj;
                }
                $resultArray[] = $obj;
            }
            return $resultArray;
        }
        return null;
    }
}

class UserProvider extends BaseDbProvider
{
    public getAll(){
        $userQueryObj = $this->di['modelsManager']->createBuilder()
            // query builder stuff

        $users = $userQueryObj->getQuery()->execute();
        return $this->output($users);
    }

    protected function output($result){
        if ($result instanceof Phalcon\Mvc\Model\Resultset\Simple){
            $users  = [];
            /** @var UserExt $r */
            foreach ($result as $r){
                $users[] = UserFactory::create($r->type, $r->toArray());
            }
            return $users;
        }
        if ($result instanceof UserExt){
            return UserFactory::create($result->type, $result->toArray());
        }
        return parent::output($result);
    }
}

I have to ask though, why do you have multiple model classes that point to the same table?

That's not quite the case. I used the devtools to generate my models and then extended them with other functionality (validations, relations etc) so i could reuse devtools to regenerate my model classes when i alter my tables, but now i want to further specialise these already extended classes.

class User extends Base
{
    // properties
    // other devtools auto generated methods
}

class UserExt extends User{
    public function initialize()
      {
          parent::initialize();

          // stuff here
      }

      public function beforeValidationOnCreate()
      { 
          // stuff here

          parent::beforeValidationOnCreate();
      }
      public function validation()
      {
          // validation stuff here
      }
 }

 class AdminUser extends UserExt{

 }

 class RegularUser extends UserExt{

 }

etc



121

I had same problem. Thanks)