Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to automatically update the timespamps of parent model when a relationship is being created or removed?

In Laravel a model that has a belongs to relationship to another, also has a <parent>_id field on its table that points to the id of the parent. When that model is being associated to another the updated_at timespamp naturally gets updated, as the value of the <parent>_id field changes.

The parent model though, the one with the has many relationship, doesn’t have any fields that change when it becomes or stops being related to a child model, so its updated_at timespamp doesn’t change.

What I want, is both the parent and the child models to automatically update their updated_at timespamps every time a relationship between the two gets created or removed. What is the proper way to achieve this?

I have already looked into the touches property, which causes the timestamp of the parent to get updated automatically when the child gets modified. But this only works when a new relationship is being created and not when an old one is being removed. And also, this will update the timestamp of the parent at the change of any field, not just of the <parent>_id and that's something that I don't actually want.

like image 788
Manolis Agkopian Avatar asked Nov 30 '16 12:11

Manolis Agkopian


People also ask

How do you make a false timestamp in laravel?

Simply place this line in your Model:public $timestamps = false; And that's it!

What is polymorphic relation in Laravel?

A one-to-one polymorphic relationship is a situation where one model can belong to more than one type of model but on only one association. A typical example of this is featured images on a post and an avatar for a user. The only thing that changes however is how we get the associated model by using morphOne instead.

Has One through relationship Laravel example?

Laravel introduces a relationship: “HasOneThrough”. This is new in Laravel Development but, other framework uses this like “Rails”. The “HasOneThrough” relationship links models through a single intermediate relation. For example, if each group will have users and users will have their users history.

How to define relationship in Laravel?

To define a relationship, we need first to define the post() method in User model. In the post() method, we need to implement the hasOne() method that returns the result. Let's understand the one to one relationship through an example. First, we add the new column (user_id) in an existing table named as posts.


1 Answers

Taken from the Laravel Docs.

Touching Parent Timestamps

When a model belongsTo or belongsToMany another model, such as a Comment which belongs to a Post, it is sometimes helpful to update the parent's timestamp when the child model is updated. For example, when a Comment model is updated, you may want to automatically "touch" the updated_at timestamp of the owning Post. Eloquent makes it easy. Just add a touches property containing the names of the relationships to the child model:

<?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');
    } }

Now, when you update a Comment, the owning Post will have its updated_at column updated as well, making it more convenient to know when to invalidate a cache of the Post model:

$comment = App\Comment::find(1);

$comment->text = 'Edit to this comment!';

$comment->save();

Update

The delete method on a model does update the owners timestamps method is taken from the Illuminate\Database\Eloquent\Model.php

To update manually you could run $this->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;
}
like image 67
Olly Campbell Avatar answered Nov 15 '22 11:11

Olly Campbell