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

Why properties of Models are lost?

Hi everyone, I am using Phalcon's ORM quite intensively these days, and I have some problems with my properties. I create a model class, derivating from \Phalcon\Mvc\Model, all is working fine.

class Test extends \Phalcon\Mvc\Model {
  // ...
  private $myProperty;
}

But if I modify $myProperty on a particlar instance of Test, I lose its value in some function (especially during validation). Is there a special reason for this behaviour?

In the same way, if I have a ResultSet, I cannot iterate on it and modify $myProperty, since accessors (iterators-like) perform a copy of the object (no a clone). Is it "by design"?

Thanks! :)



98.9k

Can you post the code where you're modifying the property and then is lost?



1.9k

Yes, I know, it would be better to post the code in the first message.... ;)

About ResultSet:

class MyModel extends \Phalcon\Mvc\Model {
    public $myProperty = 'hello';
}
//...
$all =MyModel::find();
foreach($all as $m){
    $m->myProperty= 'World'; //A clone is modified
    echo $m->myProperty, "<BR/>";
}
foreach($all as $m){
    echo $m->myProperty, "<BR/>"; //Still display the 'hello' value
}

I understand that a clone is done, but it can be annoying since normally objects are passed by reference (by default) in Php5

About property change during validation, it is a mistake... I made some rapid conclusions according to the situation above. So here the real question:

$myModel->appendMessage(new Phalcon\Mvc\Model\Message("Hello World"));;
foreach($myModel->getMessages() as $msg){
    echo $msg,"<BR/>"; //The message is displayed
}
$myModel->create(); //This statement seems to empty the current message queue
foreach($myModel->getMessages() as $msg){
    echo $msg,"<BR/>"; //No message displayed!
}

So, in fact it was not related to properties (sorry), but to the message queue that is cleaned before update/create operation. It's not a bad idea.... ;)



98.9k

Regarding the first part, when a resultset is traversed, only just one record is kept in memory, if you modify a record changes will lost, because the record is freed once it is not used anymore. This scheme is very efficient if you are traversing big resultsets, imagine if you have 10.000 records, keeping them in memory could easily use all available memory. If you still want this, you can add the records to an array, due to the reference counting, the object will not freed and you can re-use the records created.

$records = array();
$all = MyModel::find();
foreach ($all as $m) {
    $m->myProperty= 'World'; //A clone is modified
    echo $m->myProperty, "<BR/>";
    $records[] = $m;
}

foreach ($records as $m) {
    echo $m->myProperty, "<BR/>"; //changed value
}

Secondly, the ORM clear all the messages when you call create/update/save, imagine if the ORM does not have this behavior:

if (!$myModel->create()) { //saving some records producing messages

    foreach ($myModel->getMessages() as $msg) {
        echo $msg, "<BR/>"; //No message displayed!
    }

    //fixing those messages
    $myModel->xx = "yy";

    $myModel->create();

    // since create does not clear messages you'll find messages
    // from the past create
    foreach ($myModel->getMessages() as $msg) {
        echo $msg, "<BR/>"; //No message displayed!
    }

}


1.9k

About ResultSet, I forgot this 'detail', that only one record is kept in memory, so it is normal that my properties cannot be kept. About messages, it is relevant too.

So, no more questions :) Thank you very much for these explanations, and for your work!