\yii\db\ActiveRecord, eg. Post, and override instantiate():public static function instantiate($row) {
return Yii::$container->get(static::class);
}
\yii\base\Behavior, eg. PostBehavior, which contains a new user relation for Post:public function getUser() {
return $this->owner->hasOne(User::class, ['id' => 'user_id']);
}
PostBehavior to Post using DI container definitions, eg.:'container' => [
'definitions' => [
'common\models\Post' => [
'as myBehavior' => 'common\behaviors\PostBehavior',
],
],
],
Post::find()->joinWith('user')->all();Everything works fine if PostBehavior is added directly inside Post::behaviors(), but fails when included through application's DI container definitions.
Invalid Parameter – yii\base\InvalidParamException
common\modelsPost has no relation named "user".
The problem appears to lie in \yii\db\ActiveQuery::buildJoinWith(), where our ActiveRecord is being instantiated using new $this->modelClass rather than Yii::createObject($this->modelClass) thus causing the relations defined via DI-provided behaviors to be disregarded.
| Q | A
| ---------------- | ---
| Yii version | 2.0.11
| PHP version | 5.6
| Operating system | Ubuntu
Looks valid at the first sight. Would you like to fix it with a pull request containing the fix and a unit test? If yes then it has a chance to be merged into 2.0.12.
need change AR::instantiate too
@samdark I'm working on the PR + unit tests as you requested.
@lynicidn Generally you should, yes, but it didn't seem relevant to this specific case so I omitted it. I'll edit it back just to be sure.
try
$post = Post::findOne();
$user = new User();
$post->link('user', $user);
you also get exception that user relation not found
Read my post again.
if you want change logic for create models - it need do for all cases
best way:
Event::on(Post::class, 'init', function(ModelEvent $e) {
$e->sender->attachBehavior($myBehavior);
});
this global work for all cases and don't break active record design
@lynicidn This issue is about attaching behaviors via configuration, which is an officially supported feature in Yii2, so one would expect it to work consistently. The issue highlights a case in which the official feature breaks.
That said, your workaround sounds like it could work. By the way, where would you put your code to ensure it is always run before any controllers/components etc? bootstrap?
read from here https://github.com/yiisoft/yii2/issues/5786#issuecomment-192049982
@lynicidn That does not answer my question at all.