Askedio/laravel-soft-cascade

Avoid changing updated_at on restore

Closed this issue · 8 comments

First thank you for this great package!

As far as I can tell, when cascade-restoring a model, the updated_at column is changed which is a problem for my application. Is it a Laravel problem? Is it this package, and if so, is it the intended behaviour? And finally, is there a way to disable this behaviour?

Thank you in advance!

This is a functionality of Laravel and not a Laravel problem.
The use of these fields is explained in the documentation: https://laravel.com/docs/5.6/eloquent#eloquent-model-conventions

I paste you the code to use when you don't need timestamps columns.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps = false;
}

Could you explain which is the problem you have? maybe I could help you!

Thank you for the quick reply :-)

So my problem is that I'm trying to implement a recover (undo delete) functionality on a forum system.
If I delete a discussion and then recover it, the updated_at field is updated, and since I need this field to keep track of most recently updated discussions,(I order by updated_at) it changes the order of display (it put a potentially 6 months old discussion first in list).

To say it differently, I'd like to have recover() only set null the deleted_at columns without touching the others columns.

I understand it's a specific use case, but on save() you can do it like this :

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

I'd like to have

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

By the way, the application is here : https://github.com/philippejadin/agorakit

I will implement it as soon as possible :)

Great! Please note that $model->restore(['timestamps' => false]); doesn't work and afaict is not supported by laravel, so I don't know how to do it properly. I think that the updated_at column is already updated when a record is deleted (which make sense for most use cases but not mine, or general undo strategy where you want to restore a record exactly as it was before deletion).

Anyway I'm curious to see how you will solve this, learning opportunity for me there

To add to my previous comment, I think that for my use case, I'd better not cascade delete and recover at all, and just delete/recover a single element (be it a group, a discussion or a comment in my case) so the recover process doesn't propagate to parents (a comment belong to a discussion and a discussion belong to a group).

Thank you for your time!

@philippejadin This will be the best option because I'm checking Laravel code and I can't interact with model timestamps because when Laravel call runSoftDelete method restablish model with newQueryWithoutScopes method.

/**
     * Perform the actual delete query on this model instance.
     *
     * @return void
     */
    protected function runSoftDelete()
    {
        $query = $this->newQueryWithoutScopes()->where($this->getKeyName(), $this->getKey());

        $time = $this->freshTimestamp();

        $columns = [$this->getDeletedAtColumn() => $this->fromDateTime($time)];

        $this->{$this->getDeletedAtColumn()} = $time;

        if ($this->timestamps && ! is_null($this->getUpdatedAtColumn())) {
            $this->{$this->getUpdatedAtColumn()} = $time;

            $columns[$this->getUpdatedAtColumn()] = $this->fromDateTime($time);
        }

        $query->update($columns);
    }

My idea was to edit the model timestamps in real time using property setted with config as config(['softcascade.timestamps' => false]).

//Set model timestamps
if (is_bool($this->timestamps)) {
    $model = $relationModel->getModel();
    $model->timestamps = $this->timestamps;
    $relationModel = $relationModel->setModel($model);
}

I think it means something like :
"if you want to preserve exactly your models when recovering, don't cascade delete / recover in the first place" :-)

It makes sense and probably means it's a niche use case.

Thank you for taking the time to dig this.

@philippejadin You're welcome, it has been a pleasure. I think the same but another option could be to create a model that extends this by setting the timestamps = false property and using the new model when you don't want to change the date.