Cphalcon: [NFR] Implement MVC\Model property that lists Model properties to include in Model serialization

Created on 24 Sep 2013  Â·  13Comments  Â·  Source: phalcon/cphalcon

The background:

http://stackoverflow.com/questions/18984972/phalcon-mvc-model-serialization-object-properties-are-lost

Developer needs a way of telling Phalcon serializer which Model properties should be included in serialization.

Implement:

Phalcon\Mvc\Model::serializableProperties = array();

Sample code:

class Country extends Phalcon\Mvc\Model
{
    protected $serializableProperties = [
        'states' // Include in serialization.
    ];

    protected $states; // Not a table field, some custom property

    public function initialize()
    {
        $this->setSource('countries');
    }

    public function afterFetch()
    {
        if ($this->id) {
            $this->states = ['AL', 'AZ', 'NV', 'NY'];
        }
    }
}

Thanks!

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

stale

Most helpful comment

Posting here for posterity's sake. I recommend using the below approach, as opposed to the one suggested previously which involves calling the parent's serialize method - this leads to a lot of recursion / slow performance. Also, with the below you need only override serialize (and not unserialize). This is actually exactly what cphalcon is doing behind the scenes (per the source code)

public function serialize()
    {
        $metaData = $this->getModelsMetaData();
        $fields = array_merge($metaData->getAttributes($this), array(
               "_your_custom_property",
              "_your_second_custom_property"
        ));
        $data = array();
        foreach($fields as $k) {
            if (isset($this->{$k})) {
                $data[$k] = $this->{$k};
            }
        }
        return serialize($data);
    }

All 13 comments

Why not

public function __sleep()
{
    return array('states');
}

?

See http://www.php.net/manual/en/language.oop5.magic.php#object.sleep

@sjinks I've just tried that - added __sleep() to Country. Result is exactly the same. __sleep() is not invoked at all (my debugbreak() is not firing).

Ah, I see — Model implements Serializable interface.

To serialize your own properties (which \Phalcon\Mvc\Model is unaware of), you will need to use a trick like this: http://ua1.php.net/manual/en/class.serializable.php#107194

public function serialize()
{
    $data = array(
        'states' => $this->states,
        'parent' => parent::serialize(),
    );

    return serialize($data);
}

public function unserialize($str)
{
    $data = unserialize($str);
    parent::unserialize($data['parent']);
    unset($data['parent']);
    foreach ($data as $key => $value) {
        $this->$key = $value;
    }
}

Thanks, that did the trick:

    public function serialize()
    {
        $data = [
            'parent' => parent::serialize()
        ];
        if ($this->serializableProperties) {
            foreach ($this->serializableProperties as $k => $v) {
                $data[$v] = $this->$v;
            }
        }
        return serialize($data);
    }

What's your opinion on the original NFR? Listing keys to serialize is definitely easier and removes overhead.

I wouldn't put serializableProperties on the same model, maybe in a new category of ModelsMetaData

@phalcon ModelsMetaData is practically undocumented. Can you give me a hint on how to implement it?

Guys,

I would like to return to this item for a second.

Would you be so kind explaining why wouldn't Phalcon serialize all properties of a model class? I understand that a programmer may assign a Closure to Model property and so on. What is the REAL reason it behaves that way.

I'll tell you where I'm coming from. I have a Model that nests another model, which in turn may nest more models. Think about Layout->Form->Section->Page->RadioQuestion->Options hierarchy. Serialization of Layout incurs serialization of nested objects.

Long story short - using the trick outlined above really hurts the performance.

return serialize($data); is being called often enough to shoot high in the profiler. Wouldn't it be better if Phalcon serializer took care of everything?

Thanks!

@phalcon @sjinks

Sorry to bug you again, but this is a kind of sore point for me. Can I have your thoughts, please?

Why wouldn't you by default serialize everything (including non-model fields), except the object properties that are known to Phalcon?

Thanks!

@phalcon @sjinks

I will second @temuri416 inquiry about this topic as well. Excluding non phalcon model fields definitely limits flexibility on practical and common scenarios

I decided to revive this... Again! Too serious of a problem to ignore.

http://forum.phalconphp.com/discussion/1714/new-attempt-to-get-model-serializer-discussion-going

Posting here for posterity's sake. I recommend using the below approach, as opposed to the one suggested previously which involves calling the parent's serialize method - this leads to a lot of recursion / slow performance. Also, with the below you need only override serialize (and not unserialize). This is actually exactly what cphalcon is doing behind the scenes (per the source code)

public function serialize()
    {
        $metaData = $this->getModelsMetaData();
        $fields = array_merge($metaData->getAttributes($this), array(
               "_your_custom_property",
              "_your_second_custom_property"
        ));
        $data = array();
        foreach($fields as $k) {
            if (isset($this->{$k})) {
                $data[$k] = $this->{$k};
            }
        }
        return serialize($data);
    }

Something like this would be great to have.

Thank you for contributing to this issue. As it has been 90 days since the last activity, we are automatically closing the issue. This is often because the request was already solved in some way and it just wasn't updated or it's no longer applicable. If that's not the case, please feel free to either reopen this issue or open a new one. We will be more than happy to look at it again! You can read more here: https://blog.phalconphp.com/post/github-closing-old-issues

Was this page helpful?
0 / 5 - 0 ratings