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

Assigning array to model field, somehow corrupts other fields in same model?

Hi Guys,

I'm trying to assign an array to a model field. The idea is that I'm going to automatically json encode/decode this field in the beforeSave and afterFetch functions. However I haven't been able to get this far yet because assinging arrays to model fields seems to act weird.

This code demonstrates the problem:

        $test = new Test();
        $test->name = 'The Real Name';
        $test->network = array('name' => 'eth0', 'data' => 'stuff');

        var_dump($test->toArray());
        exit;

Test is an empty class extending \Phalcon\Mvc\Model

Output is this:

array (size=3)

  'id' => null

  'name' => string 'eth0' (length=4)

  'network' => null

So it seems that the content of the array is somehow assigned to the model itself?

Does anyone have any idea how to solve this?

Thanks.

PHP Version 5.5.36 MSVC11 (Visual C++ 2012)

Phalcon Version 2.1.0r Build Date Apr 8 2016 18:17:26



6.9k
Accepted
answer

This isn't a bug itself, but moreso how the __set magic method overload works with Models. You can see here https://github.com/phalcon/cphalcon/blob/efe49ef795d5a3e3d867cfd3ce8f8f69317e8152/phalcon/mvc/model.zep#L4106

That when the value is an array, it iterates through and acts on it accordingly whether it's a relationship or not.

The best thing thing to do in your case would be to use getters and setters - https://docs.phalcon.io/en/latest/reference/models.html#public-properties-vs-setters-getters

That way your code itself doesn't require changing, just 2 new methods on your model and 1 visibility scope changed on $network variable.



3.6k
edited Jul '16

Thanks you very much, it all makes sense now.

I've been able to fix it by defining the 'network' variable on the top of the model, like this:

class Test extends \Phalcon\Mvc\Model {
    public $network;
}

This prevents the magic setter from being called.

Personally I don't really like this behavior though so I've used the following code in my base model to disable it completely.

    public function __set($property, $value)
    {
        if (is_array($value)) {
            $this->{$property} = $value;

            return $value;
        }

        return parent::__set($property, $value);
    }