fuel / orm

Fuel PHP Framework - Fuel v1.x ORM
http://fuelphp.com/docs/packages/orm/intro.html
151 stars 95 forks source link

Unable to resave an object on PHP7 #392

Closed vesatoivonen closed 8 years ago

vesatoivonen commented 8 years ago

I'm unable to get the following code working on PHP7:

$user = \Model_User::find(1);
$user->name = 'foo';
$user->save();
$user->name = 'bar';
$user->save();

Only the first value foo is updated to db and similar issues seem to be troubling all my models which are all extending \Orm\Model. Also when creating multiple objects using the following observer, the counter is incremented only once.

public function _event_before_insert(){
    $this->project_number = $this->company->next_project_number;
    $this->company->next_project_number += 1;
    $this->company->save();
}

These all work fine on previous PHP versions, but at least on 7.0.4 and 7.0.6 they do not. I'm using MariaDB and disabling caches didn't help.

WanWizard commented 8 years ago

If I remember our conversation correctly, this was also the case:

$user = \Model_User::find(1);
$user->name = 'foo';
$user->save();
$user->name = 'bar';
var_dump($user->is_changed());
bool(false)

which is the reason why the second save() doesn't do anything.

Also, you said than when you forge() a new object instead of find() an an extsing one, both save() operations work fine.

vesatoivonen commented 8 years ago

Yeah, the following code results second being written to db:

$c = \Model_Foo::forge(array('name' => 'first'));
$c->save();
$c->name = 'second';
$c->save();
$c->name = 'third';
$c->save();

I've been digging around with xdebug and found out that after the first save on old objects ->set() changes both $_data and $_orginal arrays in the object rather than only $_data like it does before saving. Something to do with references I guess.

vesatoivonen commented 8 years ago

I got somewhere by dereferencing the _original array in _update_original()

    public function _update_original($original = null)
    {
        $original = is_null($original) ? $this->_data : $original;
        $this->_original = array_merge($this->_original, $original);

        $tmp = array();
        foreach ($this->_original as $key => $value){
            $tmp[$key] = $value;
        }
        $this->_original = $tmp;

        $this->_update_original_relations();
    }

With this, the resave seems to work, but I still need to fiddle a bit more to get the related objects to save properly too.