Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Model not update twice
  • Hello,

    When I updated an OrmModel attribute at first time, I get is_changed() to True and save() update my database. After I do some delayed actions and I need to change again the same attributes with an other value, but I obtain is_changed() to false and save() do nothing but when I dump the OrmModel, the value is modified in lmemory. I there an method to force un clean the record or another soluce ??

    $myModel->val='firstvalue';
    $myModel->save();  // is OK
    ...
    ...
    << actions >>
    ...
    $myModel->val='othervalue';
    $myModel->save();  // do nothing on database

    Regards.

  • Which Fuel version?
  • Version 1.8
  • I can't reproduce it in 1.9-dev. My test code:

    // create test data
    DBUtil::truncate_table('test');
    $query = DB::insert('test', array('name'))->values(array('Name'))->execute();

    // get the record
    $test = Model_Test::query()->select('id', 'name')->where('id', 1)->get_one();

    \Debug::dump($test);
    \Debug::dump($test->is_changed()); // should be False

    $test->name = 'New name';

    \Debug::dump($test->is_changed()); // should be True

    $test->save();

    \Debug::dump($test->is_changed()); // should be False

    $test->name = 'Other name';

    \Debug::dump($test->is_changed()); // should the True

    $test->save();

    The database profiler shows me it executes:

    TRUNCATE TABLE `test`
    INSERT INTO `test` (`name`) VALUES ('Name')
    SELECT `t0`.`id` AS `t0_c0`, `t0`.`name` AS `t0_c1` FROM `test` AS `t0` WHERE `t0`.`id` = 1 LIMIT 1
    UPDATE `test` SET `name` = 'New name' WHERE `id` = 1
    UPDATE `test` SET `name` = 'Other name' WHERE `id` = 1

    I have also tested this with 1.8.0, witht he same result.

    So no problems here?
  • Hum ... !!!

    I've spend time before post without find a mistake. So, I will check tonight again and use profiler so by using your method. Perharps  'gremlins' are hidden very well.

    Thanks Harron


  • If you Debug::dump() the object before the save(), check the values of _data and _original. 

    is_changed() compares the two to see if there is something that needs saving. Also, after a save(), _data and _original should be in sync.
  • Hello,

    I did new tries and I found that issue occurs only when do action on task with 'php oil refine ...'.

    Test code :
            $node->state = \Model_Manager_State::getRunning(); /* 2 */
            $node->save();
            $node->state = \Model_Manager_State::getSuccess();/* 3 */
            $node->save();
            $node->state = \Model_Manager_State::getFailed();/* 4 */
            $node->save();

    On a controller, the database is updated with the '4' value, but on a task, only the value '2' is wrote !!
    The other save() methods are executed but the model has his changed flag modified
    the dump is also good but the not the database..

    Perhaps I must wrap all into a controller and limit  statement into task with \Request::forge ?




  • That means that if you simply do this in a task:

    $node->state = 2;
    $node->save();
    $node->state = 3;
    $node->save();
    $node->state = 4;
    $node->save();

    it will fail too?

    If so I can not reproduce it, it works fine here, I end up with 4 in the database too.
  • I forgot to say that ->state is a belongs_to relation to a State Model not a direct value.

    I move my code into a controller like i wrote above and its work, it's the most important at this time for me cause I'm late in my project.

    Thanks for your interest.

  • I noticed that I must use 'from_cache' => false into model::find  to work as excepted, but I know understand why. When I show is_changed() state , I get :

    echo $obj->is_changed()  => false
    $obj->state= << other state >>
    echo $obj->is_changed()  => true
    $obj->save()
    echo $obj->is_changed()  => false but nothing on database if I don't use 'from_cache' => false !!
  • Hello again,

    I did some inspection into model.php code and put some outputs
        protected function update()
        {
            // New objects can't be updated, neither can frozen
            if ($this->is_new())
            {
                return false;
            }

            // Non changed objects don't have to be saved, but return true anyway (no reason to fail)
            if ( ! $this->is_changed(array_keys(static::properties())))
            {
            echo __METHOD__,' ',__LINE__,' __TRUE',PHP_EOL;
                return true;
            }


    .
    .
        public function is_changed($property = null)
        {
            echo '===========>',__METHOD__,' ',__LINE__,print_r($property,true),PHP_EOL;
            $properties = static::properties();
    .
    . add echo TRUE or FALSE before each return statement of is_changed() method.

    My code
                echo 'is_changed:',$first->is_changed(),PHP_EOL;
                echo '--------------------------------------',PHP_EOL;
                $first->save();
                die('-------------------------------------');

    My output
    is_changed:===========>Orm\Model::is_changed 1701
    ____ TRUE
    1
    --------------------------------------
    ===========>Orm\Model::is_changed 1701Array
    (
        [0] => state_id
        [1] => state_label
    )

    ____ FALSE
    Orm\Model::update 1426 __TRUE
    ===========>Orm\Model::is_changed 1701Array
    (
        [0] => graph_id
        [1] => step_id
        [2] => step_label
        [3] => step_function
        [4] => state_id
    )

    ____ FALSE
    Orm\Model::update 1426 __TRUE
    -------------------------------------

    Update method do nothing since thinks any properties aren't changed.. but is_changed() get true !!
  • Just to be sure I understand it:

    So "state" is a foreign key to a related table, and your issue is that the foreign key isn't updated if you change the related object and you save the parent, correct?

    Are you completely up to date with 1.8? Did you do a composer update to make sure you have all recent updates and fixes?
  • Yes to all...

  • What exactly do those static methods do?

    When I change my test code to:

    $a = \Model_TestA::find(1);
    $a->testb = \Model_TestB::find(1);
    $a->save();
    $a->testb = \Model_TestB::find(2);
    $a->save();
    $a->testb = \Model_TestB::find(3);
    $a->save();
    $a->testb = \Model_TestB::find(4);
    $a->save();
    var_dump($a);

    Both the dump and the database has test_id = 4.

  • Tried it also by creating new related objects:

    $a = \Model_TestA::find(1);
    $a->testb = \Model_TestB::forge(['name' => \Str::random());
    $a->save();
    $a->testb = \Model_TestB::forge(['name' => \Str::random());
    $a->save();
    $a->testb = \Model_TestB::forge(['name' => \Str::random());
    $a->save();
    $a->testb = \Model_TestB::forge(['name' => \Str::random());
    $a->save();
    var_dump($a);

    Both the dump and the database has the same and latest test_id.

  • Hello Harro,

    When i run by CLI , it's not good but when do run action by browser is good ??

    namespace Fuel\Tasks;

    class Schedule
    {
        public function clear($id=1) {
            $d = \Request::forge('manager/task/clear')->execute()
            ->response();
        }
    }


    class Controller_Manager_Task extends Controller
    {

        public function action_clear($id = 1)
        {
            try {
                $nodes = \Model_Manager_Step::find('all', array(
                    'where' => array(
                        array(
                            'graph_id',
                            $id
                        )
                    )
                ));
                foreach ($nodes as $step) {
                    //print_r($step);
                    $step->state = \Model_Manager_State::getRunnable();
                    $step->save();
                    $step->state = \Model_Manager_State::getSuccess();
                    $step->save(); // NO change by CLI
                }
        }
    }


    class Model_Manager_State extends \Orm\Model
    {
    .
    .
        public static function getRunnable()
        {
            if (! self::$runnable) {
                self::$runnable = self::query()->where('state_label', 'Runnable')->get_one();
            }
            self::$runnable->frozen(true);
            return self::$runnable;
        }
    .



    By browser : http://myserver/foo/public/manager/task/clear
    By cli : php oil refine schedule:clear

    I've enabled MySQL log, and by CLI, there is no UPDATE statement for the second save() action.
    Perhaps I must do this by other way, the context execution is no the same and perhaps something is missing in my way to do tasks.

    Thanks for your time on my issue.

  • I've done all my tests using a test, as you asked.

    But I now see that you have a task that calls a controller, although I don't see how that should make a difference, I'll see if I can try this later.

    What I do wonder, what is the meaning of this line?

    self::$runnable->frozen(true);

    You have to be careful with using "self" btw, use "static" instead, you need late static binding, in some cases that does make a difference.
  • Also with an HMVC call to a controller I can not reproduce it.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion