【问题标题】:Update without touching timestamps (Laravel)更新而不触及时间戳(Laravel)
【发布时间】:2013-09-25 03:19:18
【问题描述】:

是否可以在不触及时间戳的情况下更新用户?

我不想完全禁用时间戳..

grtz

【问题讨论】:

  • 默认情况下无法覆盖时间戳。我不确定,但你试过 DB::raw($yourRawQuery) 吗?

标签: php laravel laravel-4 eloquent


【解决方案1】:

暂时禁用它:

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

您可以选择在保存后重新启用它们。

这是 Laravel 4 和 5 独有的功能,不适用于 Laravel 3。

【讨论】:

  • 我遇到了这个问题...?在基本模型中设置时不起作用。其他人有问题吗?
  • 你能再解释一下吗?仍然无法使其正常工作,并且看起来很愚蠢。也使用 Laravel 3。
  • 在保存之前基本上是禁用timestamp,在Laravel 3中该属性是静态的,所以我不确定你是否可以在运行时更改它,看看代码:github.com/laravel/laravel/blob/3.0/laravel/database/eloquent/…
  • 这是唯一对我有用的解决方案。我曾尝试过更“优雅”的方式:$something->save(['timestamps'=>false]);,但它只是忽略了它。非常感谢!
  • 如果模型定义了“接触”,这仍然会导致关系更新。
【解决方案2】:

在 Laravel 5.2 中,您可以将公共字段 $timestamps 设置为 false,如下所示:

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

或者您可以将选项作为save() 函数的参数传递:

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

要更深入地了解它的工作原理,您可以查看 \Illuminate\Database\Eloquent\Model 类,在方法 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();
    }

    // [...]

仅当公共属性timestamps 等于trueArr::get($options, 'timestamps', true) 返回true 时才会更新时间戳字段(如果$options 数组不包含键timestamps,则默认情况下会这样做)。

只要这两个返回falsetimestamps 字段就不会更新。

【讨论】:

  • 请注意,此功能在 Laravel 5.1 和 5.2 中被破坏,因此已从 Laravel 5.3 中删除。见:github.com/laravel/framework/issues/10028
  • 它在 laravel 8 中不起作用
  • 未测试,但在 Laravel 8 中似乎可以在调用 update() 方法之前将模型 $timestamps 的属性设置为 FALSE。
【解决方案3】:

补充安东尼奥·卡洛斯·里贝罗的回答

如果您的代码需要超过 50% 的时间停用时间戳 - 也许您应该禁用自动更新并手动访问它。

在 eloquent 中,当您扩展 eloquent 模型时,您可以通过放置禁用时间戳

更新

public $timestamps = false;

在你的模型中。

【讨论】:

  • 这对我不起作用,我必须这样做public $timestamps = false;
  • 修正了我对@JonathanEllis 所说的回答 - 它现在是公共财产
  • 真的是public,而不是protected(可见性)?
【解决方案4】:

以上示例效果不错,但仅适用于单个对象(每次仅一行)。

如果您想更新整个集合,这是一种临时禁用时间戳的简单方法。

class Order extends Model
{

 ....

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

}

现在你可以简单地调用这样的东西:

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

【讨论】:

  • 它的 Order:: w ithoutTimestamps(),请修复
【解决方案5】:

如果您需要更新单一模型查询:

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

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

如果您需要更新多个模型查询使用

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

而不是

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

【讨论】:

  • 当他们的意思是“实例”时,每个人都称它为“模型”。模型不是实际的实例,它只是不是实际真实对象的类/定义。遗憾的是,这是一个普遍存在的谎言。
【解决方案6】:

对于尝试执行Model::update() 调用的 Laravel 5.x 用户,您可以使用

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

由于 Model::update 函数不再接受第二个参数。 参考:laravel 5.0 api

已在 5.2 版上测试并运行。

【讨论】:

  • 这在 Laravel 5.8 中非常有用,当我一次性更新多个记录并且我不想触及 updated_at 功能的默认过程时。
【解决方案7】:

我遇到了需要进行涉及连接的大规模更新的情况,因此updated_at 导致重复列冲突。我用这段代码修复了它,不需要范围:

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

【讨论】:

    【解决方案8】:

    对于 Larvel 5.1,您也可以使用以下语法:

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

    【讨论】:

    • 在 Laravel 5.7 中对此进行了测试,但它不起作用
    • Laravel 5.7:Type: InvalidArgumentExceptionMessage: Unexpected data found.
    【解决方案9】:

    Laravel 8

    使用播种机做一些覆盖,在一项测试中我有:

    $item = Equipment::where('name', item_name))->first();
    $item->description = 'some description';
    $item->save(['timestamps' => false]);
    

    这很好用,但如果我使用firstOrNew,那么$item->save(['timestamps' => false]); 就不起作用。

    // This does not work on Seeder file
    $item = Model::firstOrNew(['name' => 'item_name']);
    $item->description = 'some description';
    $item->save(['timestamps' => false]);
    
    // Doing the following works tho
    $item = Model::firstOrNew(['name' => 'item_name']);
    $item->description = 'some description';
    $item->timestamps = false;
    $item->save();
    

    所以在某些情况下,您会使用其中一个...只需检查 die 和 dump 以查看是否 +timestamps: false

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

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

    编辑: 在我的项目中,我选择使用$item->timestamps = false;,所以我也建议使用它。这是来自 laravelplayground 的工作 sn-p: https://laravelplayground.com/#/snippets/4ae950f2-d057-4fdc-a982-34aa7c9fee15

    检查 Laravel api 上的 HasTimestamps: https://laravel.com/api/8.x/Illuminate/Database/Eloquent/Concerns/HasTimestamps.html

    以及模型上的保存方法: https://laravel.com/api/8.x/Illuminate/Database/Eloquent/Model.html

    save 方法仍然接受选项,但传递时间戳将不起作用。

    【讨论】:

    • 不起作用...
    • @Gass 你能告诉我你试过哪一个,但在你的情况下没有用。在某些情况下,您应该使用$item->timestamps = false; 而不是$item->save(['timestamps' => false]);。我提到的一种方法应该有效。
    • 是的,这正是发生的事情 $item->save(['timestamps' => false]); 在我的 Laravel 8 应用程序上不起作用
    • @Gass for laravel 8 $item->timestamps = false; 会像我在帖子中提到的那样工作。我在这里在 laravel 操场上模拟了一个代码 sn-p:laravelplayground.com/#/snippets/…
    猜你喜欢
    • 2018-12-27
    • 2014-05-21
    • 2015-10-02
    • 1970-01-01
    • 2011-02-20
    • 2014-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多