Related model set to null after setting properties in foreach loop

I am currently working on migrating an older Application from PHP 5.6 to 7.2.4 While doing so I came a cross a problem I can’t quite wrap my head around regarding related ActiveRecords suddenly being set to null after setting model properties in a foreach loop.
The user provides information via a form, which is processed in a POST-Request. The basic process looks like this:

  1. Loading the currently saved data for ModelA from the database.

  2. Setting all attributes to -9 to indicate non relevant fields in the dataset (not provided by formdata via post).

  3. Loading the provided formdata into the Model and saving it.

Simplified Example:

ModelA and ModelB are both ActiveRecords.

ModelA has a ‘hasOne()’ Relation with ModelB.


// 1. Loading the currently saved Data

$modelA = ModelA::find()->where(['id' => 1])->limit(1)->one();

// 2. Setting all attributes to '-9' to indicate irrelevant fields

foreach($modelA as $key => $val) {

$modalA->$key = -9;

}
// Setting a property in the related Model (this is where the error happens)
$modelA->modelB->porpX = -9;

// 3. loading formdata provided into the model and saving it

$modelA->load(Yii::$app->request->post());

$modelA->modelB->load(Yii::$app->request->post());

$modelA->save();

$modelA->modelB->save();

The problem at hand is that once the foreach loop has done its job I can no longer access the related ModelB and it’s properties, e.g. with ‘$modelA->modelB->propA’. This results in a PHP Exception “Attemp to read property ‘propX’ on null”. I don’t really understand why this is happening and would greatly appreciate any help.

Old System: PHP 5.6.3 and yii2 2.0.10.
New System: PHP 7.2.4 and yii2 2.0.49.2

I tried to test if it’s a general php problem creating a simple fiddle, but here it seems to be working as it used to before upgrading to the newer versions.

in controler two models use: $model1 and $model2
if ($model1->load(Yii::$app->request->post()) && $model2->load(Yii::$app->request->post())){

}

Check if this can be the reason:
https://www.php.net/manual/en/migration70.incompatible.php#migration70.incompatible.foreach

modelA->attributes?
https://www.yiiframework.com/doc/api/2.0/yii-base-model#$attributes-detail

I guess the foreign key isn’t preserved.

1 Like

I already tried passing the $val by reference in the loop, but the error would still persist. However I think I found the problem. While running the loop every property in ModelA gets set to ‘-9’. That includes the foreignkey that links to modelB. Before this would seemingly not have any negative effects, because the model was already fully loaded. But now it seems to be a problem when trying to call on the related modelB. Meaning if the foreignkey property in ModelA is not correctly set to the corresponding ModelB while calling on ‘$modelA->modelB’ this will return null for the related Model and therefore cause the execption.

I added an if-statement to exclude the foreign key from the changes inside the foreach loop and now everything seems to work fine again.

foreach($modelA as $key => $val) {
  if($key != 'modelB_id') {
    $modalA->$key = -9;
  }
}

Thanks for your reply!