gabordemooij / redbean

ORM layer that creates models, config and database on the fly
https://www.redbeanphp.com
2.31k stars 279 forks source link

Fatal error unsetting string offset via `$bean->inject($foo)` with hydrated relation #544

Closed dominics closed 7 years ago

dominics commented 7 years ago

The foreach loop in import isn't correctly handing cases where it's given an array value that doesn't contain arrays of $listItem "shape" (i.e. they don't have a _type key, or aren't arrays at all).

Specifically, the code at https://github.com/gabordemooij/redbean/blob/75c3982dc03423f64a722d40c987073f59d038b0/RedBeanPHP/OODBBean.php#L478,L488 (particularly the foreach at L486) makes the invalid assumption that if $value is an array, it must be an array of arrays.

This shows up when calling $bean->inject($otherBean) in the presence of lazy-loaded related beans.

Reproducing

A few things necessary to reproduce:

Here's a full test script to reproduce: https://gist.github.com/dominics/58b423df4458eef0a99f8d88c36f03bc

Basically, it's just:

$retrieved = R::findOne('child', 'name = ?', ['Jack']);
$retrieved->parent; // Load some relation
$fresh = R::dispense('child');
$fresh->inject($retrieved);

Errors

The specific errors are (under PHP 7.1):

Warning: Illegal string offset '_type' in /vagrant/redbug/vendor/gabordemooij/redbean/RedBeanPHP/OODBBean.php on line 487

Call Stack:
    0.1119     347776   1. {main}() /vagrant/redbug/test.php:0
    0.1821     630128   2. RedBeanPHP\OODBBean->inject(???) /vagrant/redbug/test.php:48
    0.1821     630880   3. RedBeanPHP\OODBBean->import(???, ???, ???) /vagrant/redbug/vendor/gabordemooij/redbean/RedBeanPHP/OODBBean.php:551

Fatal error: Uncaught Error: Cannot unset string offsets in /vagrant/redbug/vendor/gabordemooij/redbean/RedBeanPHP/OODBBean.php on line 488

Error: Cannot unset string offsets in /vagrant/redbug/vendor/gabordemooij/redbean/RedBeanPHP/OODBBean.php on line 488

Call Stack:
    0.1119     347776   1. {main}() /vagrant/redbug/test.php:0
    0.1821     630128   2. RedBeanPHP\OODBBean->inject(???) /vagrant/redbug/test.php:48
    0.1821     630880   3. RedBeanPHP\OODBBean->import(???, ???, ???) /vagrant/redbug/vendor/gabordemooij/redbean/RedBeanPHP/OODBBean.php:551
gabordemooij commented 7 years ago

Hi thanks for reporting this issue.

I see why this is confusing. Unfortunately inject() was never designed for this purpose, just for simple arrays.