11

following this answer, I do model save callbacks (similar to rails) in Laravel like so:

class LessonPlan extends Eloquent {

   public function save(array $options = array())
   {
      // before save code 
      parent::save();
      // after save code
   }
}

However, I call save() on Page when i'm saving a new page or updating an existing one. How do I know which is which in this operation?

I tried something like

public function save(array $options = array())
{
    // before save code
    $oldLesson = clone $this;
    parent::save();

    ..
    if ($this->isLessonStatusChanged($oldLesson)) {
      ..
    }
}

private function isLessonStatusChanged($oldLesson) {
    return $this->status != $oldLesson->status;
}

but that's no good.. since $oldLesson will already have the new values of $lesson

what I ended up doing was simply regexing the url to see if it's an update request.. but I'm already having trouble sleeping at night (my answer doesn't really tell me if any values have actually changed.. b/c one can submit an update form without actually changing anything).. is there a cleaner way of doing this?

Community
  • 1
  • 1
abbood
  • 23,101
  • 16
  • 132
  • 246
  • But why is `$oldLesson` supposed to have new values, if you just clone the object, but not make a reference to it..? – sybear Apr 16 '14 at 11:48
  • i'm wondering the same thing @Jari.. i'm assuming save here only means a database transaction or something.. i doesn't imply that what's before it will have the old values of the item.. then again I'm no Laravel expert – abbood Apr 16 '14 at 11:49
  • What you can do is to ask people on live chat here: http://laravel.io/chat Even Taylor Otwell (creator of laravel) is pretty often online. – sybear Apr 16 '14 at 11:59
  • Have you considered using Event::fire() and (where ever you want to listen for it) Event::listen() before or after the parent::save ? – alou Apr 16 '14 at 12:11
  • @alou that sounds like a bit of an overkill.. a hacky overkill that is – abbood Apr 16 '14 at 12:13
  • possible duplicate of [Detect changes when saving Laravel 4: Eloquent](http://stackoverflow.com/questions/20179711/detect-changes-when-saving-laravel-4-eloquent) – Gadoma Apr 16 '14 at 12:37

2 Answers2

14

You can use the isDirty() method which returns a bool and getDirty() which returns an array with the changed values.

public function save(array $options = array())
{
    $changed = $this->isDirty() ? $this->getDirty() : false;

    // before save code
     parent::save();

    // Do stuff here
    if($changed)
    {
        foreach($changed as $attr)
        {
            // My logic
        }
    }

}
afarazit
  • 4,907
  • 2
  • 27
  • 51
  • your `isDirty()` is missing a parameter.. this is what i did: `return $this->isDirty("status");` – abbood Apr 16 '14 at 13:22
  • 1
    @abbood nope, a parameter isn't required, https://github.com/laravel/framework/blob/master/src/Illuminate/Database/Eloquent/Model.php#L2578-L2596 – afarazit Apr 16 '14 at 17:18
  • we're looking at two different versions, you're pointing to 4.1+, i'm looking at [4.0](http://laravel.com/api/source-class-Illuminate.Database.Eloquent.Model.html#2144) – abbood Apr 17 '14 at 05:38
  • Ah alright, you haven't mentioned that so I thought you were using the latest, if you don't want to use `isDirty('status')` you could also do `count(getDirty()) > 0` like in 4.1. – afarazit Apr 17 '14 at 10:35
  • that's oright bro your answer helped me just fine.. i awarded you a correct answer after all ;) – abbood Apr 17 '14 at 10:38
0

Have you tried Model::getDirty()? I haven't tried it myself but it returns the attributes that have changed since the last sync. See the API docs.

3472948
  • 801
  • 4
  • 15