We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Can't update related model's fields

Hi!

I use Phalocn 1.3.4 and it's ORM doesn't change value of the related model's field.

Example: I have 2 models. Page model:

<?php

namespace Common\Model;

class Page extends BaseModel
{

    public $id;
    public $name;
    public $page_url;

    public $meta_id;

    public function initialize()
    {
        $this->hasOne('meta_id', 'Common\Model\Meta', 'id', [
            'alias' => 'Meta'
        ]);
    }

And Meta model:

<?php

namespace Common\Model;

class Meta extends BaseModel {

    public $id;
    public $meta_title;
    public $meta_description;
    public $meta_key_words;

}

Everything is simple, Page has one Meta

When I'm trying to create a Page everything is ok.

$page = new \Common\Model\Page();
$page->name = 'page\'s name';
$page->page_url = 'page\'s url';

$meta = new \Common\Model\Meta();
$meta->meta_title = 'page\'s title';
// an assignment of other fields

$page->Meta = $meta;
if (!$page->save()) {
    // some action
}

But here something strange is going on when I want to update the meta of the page.

// First case
$page = \Common\Model\Page::findFirst("id='1'"); // Everything is ok

$page->Meta->meta_title = 'Some other title'; 
var_dump($page->Meta->meta_title); // shows old meta_title

$page->Meta->meta_description = 'Some other description';
var_dump($page->Meta->meta_title); // shows old meta_description again

$page->save(); // updates ONLY description!!! O_O.

// Second case
$page = \Common\Model\Page::findFirst("id='1'"); // Everything is ok

$page->Meta->meta_description = 'Some other description';
var_dump($page->Meta->meta_title); // shows old meta_description again

$page->Meta->meta_title = 'Some other title'; 
var_dump($page->Meta->meta_title); // shows old meta_title

$page->save(); // updates ONLY title!!! O_O.

So it saves the last assignment but ignores all the previous ones.

$page = \Common\Model\Page::findFirst("id='1'"); 
$meta = $page->Meta;
$meta->meta_title = 'Some other title'; 
$meta->save(); // Everything is ok.

It looks like a bug :(



6.4k
Accepted
answer

Each time you access a property that is not in lowercase and is a relationship \Phalcon\Mvc\Model calls models manager getRelationRecords method. Ex:

<?php

$page->Meta->meta_title = 'Some other title'; // First query
var_dump($page->Meta->meta_title); // Second query

$page->Meta->meta_description = 'Some other description'; // Third
var_dump($page->Meta->meta_title); // ...

So you are updating different objects each time

I solved it extending __get method in Model

<?php

abstract class Model extends \Phalcon\Mvc\Model {

    public function __get($property) {
        $lowerProperty = strtolower($property);

        if (property_exists($this, $lowerProperty)) {
            return $this->$lowerProperty;
        }

        return parent::__get($property);
    }

}

I've readed a lot of Phalcon code, but in this case I don't know if it's a bug or a desired behavior

This is a common problem lots of people encounter. Another solution is to just re-set the whole Meta object:

$page = \Common\Model\Page::findFirst("id='1'"); // Everything is ok
$Meta = $page->Meta;

$Meta->meta_title = 'Some other title';
$Meta->meta_description = 'Some other description';

$page->Meta = $Meta;
$page->save();


2.3k

Thank you, guys. Both answers are helpful.



25.7k
edited Apr '15

"Each time you access a property that is not in lowercase and is a relationship \Phalcon\Mvc\Model calls models manager getRelationRecords method."

Currently I'm having problems with related model update, thanks for your big hint and it may prevent a lot of errors in the future. Did you find it by experiments or there is somewhere in the doc mentioning it? And seem like if lowercase name is the only possibility (like 'robots' it should not be camelized vs 'robotParts' which is possible to be camelized) then it is still returning the same object, is it correct? Thanks a lot (y).

"Each time you access a property that is not in lowercase and is a relationship \Phalcon\Mvc\Model calls models manager getRelationRecords method."

Currently I'm having problems with related model update, thanks for your big hint and it may prevent a lot of errors in the future. Did you find it by experiments or there is somewhere in the doc mentioning it? And seem like if lowercase name is the only possibility (like 'robots' it should not be camelized vs 'robotParts' which is possible to be camelized) then it is still returning the same object, is it correct? Thanks a lot (y).

I found it while debugging, searching in Phalcon source code.

When you access robotParts default model::__get() method calls manager::getRelationRecords() and then sets the property in lowercase, so then with this fix accessing the property in any combination of lowercase and uppercase letters will do the same