Experienced Help: ActiveRecord related model is null even if relation is well defined and link attribute is correctly set

Hello everyone, I’ve been using Yii2 everyday for the last 4 years and I can’t get over this mysterious issue.

I have a for loop in which I access a related model if the id in the main model is set. Like this:

<?php

/**
 * @property $modelB_id
 */
class ModelA extends yii\db\ActiveRecord
{
    public function getModelB()
    {
        return $this->hasOne(ModelB::class, ['id' => 'modelB_id']);
    }
}

class ModelB extends yii\db\ActiveRecord
{}

$models = ModelA::find()->where(/** blabla */);
foreach ($models->each() as $modelA) {
    echo $modelA->modelB_id;                    //outputs a number
    
    var_dump($modelA->modelB);                  //outputs NULL
    
    if ($modelA->modelB_id) {
        $modelB = $modelA->modelB;
        
        //expect $modelB to not be null
    }
}

Now this works great for many models until I get one that has a valid $modelB_id set (there’s even a FK constraint involved) but upon calling $modelA->modelB it returns null, so my code fails later on with
Exception: Trying to get property of non-object when I try to access properties of modelB.

Do you have any idea of what may cause this and what steps I could take to further investigate the issue? I’m kinda stuck.
Thanks

Hm, hard to say. First thing that comes to my mind is that while $modelA->modelB_id is in fact a number, there is no ModelB with that id hence the relation object is null. Is it the case?

Thanks for the answer.
No it’s not, I verified that a record for model B with that id exists, as I stated there is a foreign key constraint check active on that column.

Thanks to your answer I’ve focused more on why that specific record was causing this issue. What is specific of it? I asked myself.

It turns out that a soft delete mechanism is implemented for ModelB and that record was in fact soft deleted. The find() method was overriden like this:

public static function find()
{
    return parent::find()->where(['isDeleted' => false]);
}

Thank you for the help!

1 Like