3

I'm incrementing some total fields in my table

$model->total_comments += 1;
$model->save();

However this triggers the date to update for updated_at. I want to disable it for these cases. I know I can do it manually and disable auto update for the the timestamp fields altogether. But hoping there is a simple way to do it.

EDIT:

Adding example from my code. Note that there are no Observers set on this model.

namespace App\Models;

class Language extends \Illuminate\Database\Eloquent\Model
{

}

$router->get('/test', function () {
    $model = \App\Models\Language::find(1);

    $model->words_total = $model->words_total + 1;
    $model->save(['timestamps' => false]);

    return 'boo';
});
Rob
  • 10,851
  • 21
  • 69
  • 109
  • So you don't want timestamps when updating? – aldrin27 Aug 24 '15 at 07:29
  • Whenever I find myself "needing" to disable the updated time stamp; I conclude that I have an attribute in my model that does not belong there. I would not define `total_comments` as a property of the model, I would count the numbers of comments. Try to keep the database normalized. – Thomas Jensen Aug 24 '15 at 12:34

5 Answers5

5

Note there is currently a bug in the framework that prevents the first solution from working. I will keep this post up to date if it get's fixed. Github issue


You can pass an options array to save() and disable timestamps for that one save:

$model->save(['timestamps' => false]);

Of course you could also set the property on the model, but this would require you to set it back to true if there is the possibility that you are going to continue to work with the same model instance:

$model->timestamps = false;
$model->save();
$model->timestamps = true;
lukasgeiter
  • 147,337
  • 26
  • 332
  • 270
  • Not sure what's going on with the `->save(['timestamps' => false)`. When I do `->getDirty()` it doesn't show the `updated_at`. I can even comment out the `updateTimestamps` method in `Eloquent\Model`. Also disabled all observers. The thing still updates the `updated_at` field. I'm getting it from cache, but don't see how that should matter. It also inherits from a parent model, which then inherits from a `BaseModel`. As the `updateTimestamps` method is completely commented out (and dump-autoload run) I can't find the source of how this is still updating. – Rob Aug 24 '15 at 10:10
  • Strange. Is it possible that your database actually updates the field with a new timestamp? (in mysql with `ON UPDATE CURRENT_TIMESTAMP`) To be certain, log DB queries and see what Eloquent actually executes. – lukasgeiter Aug 24 '15 at 10:16
  • I have a debug bar and it is including the `updated_at` in the update query. I've checked the table and see no auto update there. When I do it through the second method by manually enabling/disabling `$model->timestamps` it doesn't fire. I guess it would mean it's not from the MySQL end in this case. – Rob Aug 24 '15 at 10:45
  • Hmm. From just looking at the framework code I don't see a reason why the option shouldn't work... [view on Github](https://github.com/laravel/framework/blob/5.1/src/Illuminate/Database/Eloquent/Model.php#L1547) – lukasgeiter Aug 24 '15 at 10:51
  • 1
    Not an Eloquent expert, but maybe some bug in the Builder. if you look at `Illuminate\Database\Eloquent\Model@performUpdate` method there is a line `$this->setKeysForSaveQuery($query)->update($dirty);` which from `setKeysForSaveQuery` receives a `Builder` object. The update is being called from that `Builder` which seems to ONLY check the models `timestamps` field and no longer the `timestamps` argument. Inside of `Illuminate\Database\Eloquent\Builder@update` there is a line `return $this->query->update($this->addUpdatedAtColumn($values));` which if you follow along will set the update field. – Rob Aug 24 '15 at 11:30
  • That definitely looks like a bug to me! I'll look into it and fix it if I can. I'll keep you posted. – lukasgeiter Aug 24 '15 at 12:36
2

You can disable the timestamps temporarily by doing this before save.

$model->timestamps = false;
Roboroads
  • 1,602
  • 1
  • 13
  • 24
1

Disable it for temporary

$model->total_comments += 1;
$model->timestamps = false;
$model->save();
Imtiaz Pabel
  • 5,307
  • 1
  • 19
  • 24
0

Solution-1:

$model = Table::find($planId);
$model->timestamps = false;
$model->increment('popularity');
$model->save();

Solution-2:

DB::table('Table')
->where(‘id’, $planId)
->increment(‘popularity’,1)

for more information https://medium.com/@panjeh/laravel-eloquent-model-increment-with-or-without-updating-timestamps-1274c6cd7f52

xpredo
  • 1,282
  • 17
  • 27
0

You can update a record without changing the created_at or updated_at timestamps by saving the current value of those columns e.g in updated_at:

Model::where('id', $id)->update(['column' => "value", 'updated_at' => DB::raw('updated_at')]);

You may also check this thread Update without touching timestamps (Laravel).