ActiveQuery dynamic $modelClass update

Hello there,

For my current web site, I have created some models extending the ones generated by gii. That way, I think, it would be easier and faster to update my DB without overwritting the changes I could have done on the generated files when I run gii again.

The process is like, more or less:

DB tables:

  • [font="Courier New"]user[/font]

  • [font="Courier New"]project[/font]

Models generated by gii

  • [font="Courier New"]User[/font]

  • [font="Courier New"]Project[/font]

Models I have created (the ones who have the business logic)

  • [font="Courier New"]UserCore[/font] (extending [font="Courier New"]User[/font])

  • [font="Courier New"]ProjectCore[/font] (extending [font="Courier New"]Project[/font])

The bad thing about this is that when I run this code:




<?php

// ...

$user_core = UserCore::findOne("1");

$projects = $user_core->getProjects()->all();



The variable [font="Courier New"]$projects[/font] is an array of [font="Courier New"]Project[/font] instead of [font="Courier New"]ProjectCore[/font].

And I was wondering how can I, dynamically, change the generated object class and I have made this:




<?php

// file config/web.php

// ...

    'on beforeRequest' => function($event) {

        \yii\base\Event::on(\yii\db\ActiveQuery::className(), \yii\db\ActiveQuery::EVENT_INIT, function($event) {

            if (isset(\Yii::$app->params['activeRecordClassAliases'][$event->sender->modelClass])) {

                $event->sender->modelClass = \Yii::$app->params['activeRecordClassAliases'][$event->sender->modelClass];

            }

        });

    },


// ...




// file web/params.php

// ...

    'activeRecordClassAliases' => [

        'app\models\gii\Project' => '\app\models\core\ProjectCore',

        'app\models\gii\User' => '\app\models\core\UserCore',

    ]

// ...



Which basically says:

On every web request, when the event [font="Courier New"]init[/font] is fired for any [font="Courier New"]ActiveQuery[/font], set [font="Courier New"]$modelClass[/font] to its corresponding [font="Courier New"]*Core[/font] model classname.

What do you guys think about this approach? Isn’t it elegant? Is it clever? Do you have alternatives?

I would love to hear what you say.

Cheers

I’m using this solution: https://github.com/schmunk42/yii2-giiant

Generates the same structure you use, i.e. auto-generated database representations and inheriting classes where you put your logic.

It looks very promising. Thanks for the suggestion Patrick