Update without touching timestamps (Laravel)

2019-01-21 12:35发布

问题:

Is it possible to update a user without touching the timestamps?

I don't want to disable the timestamps completly..

grtz

回答1:

Disable it temporarily:

$user = User::find(1);
$user->timestamps = false;
$user->age = 72;
$user->save();

You can optionally re-enable them after saving.

This is a Laravel 4 and 5 only feature and does not apply to Laravel 3.



回答2:

In Laravel 5.2, you can set the public field $timestamps to false like this:

$user->timestamps = false;
$user->name = 'new name';
$user->save();

Or you can pass the options as a parameter of the save() function :

$user->name = 'new name';
$user->save(['timestamps' => false]);

For a deeper understanding of how it works, you can have a look at the class \Illuminate\Database\Eloquent\Model, in the method performUpdate(Builder $query, array $options = []) :

protected function performUpdate(Builder $query, array $options = [])
    // [...]

    // First we need to create a fresh query instance and touch the creation and
    // update timestamp on the model which are maintained by us for developer
    // convenience. Then we will just continue saving the model instances.
    if ($this->timestamps && Arr::get($options, 'timestamps', true)) {
        $this->updateTimestamps();
    }

    // [...]

The timestamps fields are updated only if the public property timestamps equals true or Arr::get($options, 'timestamps', true) returns true (which it does by default if the $options array does not contain the key timestamps).

As soon as one of these two returns false, the timestamps fields are not updated.



回答3:

To add to Antonio Carlos Ribeiro's answer

If your code requires timestamps de-activation more than 50% of the time - maybe you should disable the auto update and manually access it.

In eloquent when you extend the eloquent model you can disable timestamp by putting

UPDATE

public $timestamps = false;

inside your model.



回答4:

Above samples works cool, but only for single object (only one row per time).

This is easy way how to temporarily disable timestamps if you want to update whole collection.

class Order extends Model
{

 ....

    public function scopeWithoutTimestamps()
    {
        $this->timestamps = false;
        return $this;
    }

}

Now you can simply call something like this:

Order::withoutTimestamps()->leftJoin('customer_products','customer_products.order_id','=','orders.order_id')->update(array('orders.customer_product_id' => \DB::raw('customer_products.id')));


回答5:

For Laravel 5.x users who are trying to perform a Model::update() call, to make it work you can use

Model::where('example', $data)
     ->update([
       'firstValue' => $newValue,
       'updatedAt' => \DB::raw('updatedAt')
     ]);

As the Model::update function does not take a second argument anymore. ref: laravel 5.0 api

Tested and working on version 5.2.



回答6:

You can also use this syntax:

Model::where('Y', 'X')
    ->update(['Y' => 'Z'], ['timestamps' => false]);


回答7:

I ran into the situation of needing to do a mass update that involves a join, so updated_at was causing duplicate column conflicts. I fixed it with this code without needing a scope:

$query->where(function (\Illuminate\Database\Eloquent\Builder $query) {
    $query->getModel()->timestamps = false;
})


回答8:

If you need to update single model queries:

$product->timestamps = false;
$product->save();

or

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

If you need to update multiple model queries use

DB::table('products')->...->update(...)

instead of

Product::...->update(...)


回答9:

IN Laravel 5.7 Increment the post view count without change the updated_at

$post->update(['view_count' => $post->view_count + 1, 'updated_at' => false]);