【问题标题】:How to automatically update the timespamps of parent model when a relationship is being created or removed?创建或删除关系时如何自动更新父模型的时间戳?
【发布时间】:2016-11-30 12:16:35
【问题描述】:

在 Laravel 中,一个模型与另一个模型具有 belongs to 关系,它的表上也有一个 <parent>_id 字段指向父模型的 id。当该模型与另一个模型相关联时,updated_at 时间戳自然会随着<parent>_id 字段的值的变化而更新。

尽管父模型,即具有has many 关系的模型,当它成为或停止与子模型相关时,没有任何字段会发生变化,因此它的updated_at 时间戳不会改变。

我想要的是,每次创建或删除两者之间的关系时,父模型和子模型都会自动更新它们的 updated_at 时间戳。实现这一目标的正确方法是什么?

我已经查看了touches 属性,它会导致父级的时间戳在子级被修改时自动更新。但这仅在创建新关系时有效,而在删除旧关系时无效。而且,这将在更改任何字段时更新父级的时间戳,而不仅仅是<parent>_id,这是我实际上并不想要的。

【问题讨论】:

    标签: laravel laravel-5 eloquent laravel-5.3


    【解决方案1】:

    取自Laravel Docs。

    感人的父时间戳

    当一个模型 belongsTo 或 belongsToMany 另一个模型,例如属于 Post 的 Comment 时,有时在子模型更新时更新父模型的时间戳会很有帮助。例如,当Comment 模型更新时,您可能希望自动“触摸”拥有Post 的updated_at 时间戳。 Eloquent 让事情变得简单。只需将包含关系名称的 touches 属性添加到子模型:

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Comment extends Model {
    
        /**
         * All of the relationships to be touched.
         *
         * @var array
         */
         protected $touches = ['post'];
    
        /**
         * Get the post that the comment belongs to.
         */
        public function post()
        {
            return $this->belongsTo('App\Post');
        } }
    

    现在,当您更新 Comment 时,拥有的 Post 也会更新其 updated_at 列,从而更方便地了解何时使 Post 模型的缓存无效:

    $comment = App\Comment::find(1);
    
    $comment->text = 'Edit to this comment!';
    
    $comment->save();
    

    更新

    模型上的删除方法确实会更新所有者的时间戳 方法取自 Illuminate\Database\Eloquent\Model.php

    要手动更新,您可以运行 $this-&gt;touchOwners();

    public function delete()
    {
        if (is_null($this->getKeyName())) {
            throw new Exception('No primary key defined on model.');
        }
    
        // If the model doesn't exist, there is nothing to delete so we'll just return
        // immediately and not do anything else. Otherwise, we will continue with a
        // deletion process on the model, firing the proper events, and so forth.
        if (! $this->exists) {
            return;
        }
    
        if ($this->fireModelEvent('deleting') === false) {
            return false;
        }
    
        // Here, we'll touch the owning models, verifying these timestamps get updated
        // for the models. This will allow any caching to get broken on the parents
        // by the timestamp. Then we will go ahead and delete the model instance.
        $this->touchOwners();
    
        $this->performDeleteOnModel();
    
        $this->exists = false;
    
        // Once the model has been deleted, we will fire off the deleted event so that
        // the developers may hook into post-delete operations. We will then return
        // a boolean true as the delete is presumably successful on the database.
        $this->fireModelEvent('deleted', false);
    
        return true;
    }
    

    【讨论】:

    • 请阅读问题的最后一段,这正是我最初尝试的方法,正如我所说,它仅在创建新关系时有效,但在删除旧关系时无效。
    • delete 方法将在删除时更新父模型。请参阅编辑 Illuminate\Database\Eloquent\Model.php 中的删除方法
    【解决方案2】:

    您可以使用 Eloquent 提供的 touch 方法来更新父级的 updated_at 时间戳。

    $parent->touch(); //will update updated_at 
    

    如果我没有误解,我想不出一种“自动”执行此操作的方法,除了在需要时调用此内联函数或在子级上使用适当的 Eloquent Events(例如,创建和删除或创建和删除)用于触摸父母的时间戳。

    【讨论】:

    • 我希望有一种方法可以自动执行此操作,但环顾四周后,您似乎是对的。由于这是唯一的答案,我将其标记为已接受。所以,看来每次更新关系时我都必须手动调用 touch 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-06
    • 2018-11-17
    • 2013-09-28
    • 2021-10-30
    • 2020-02-18
    • 1970-01-01
    相关资源
    最近更新 更多