Reputation: 1024
Something I find puzzling in Laravel 5 is how it handles the the deleting event and any changed attributes. Basically a soft delete is just an update of the deleted_at column on the table. I was trying to be clever and also include the user ID of the user making the delete. Problem is the deleting method ignores the changed attributes when passing them to the query builder.
Take this model for example.
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
use SoftDeletes;
protected $table = 'users';
protected $fillable = [
'user_name', 'created_at', 'created_by', 'updated_at', 'updated_by', 'deleted_at'
];
public static function boot() {
parent::boot();
// This works and updates my updated_by column
User::updating(function($user) {
$user->updated_by = 1;
});
// This is being ignored and does not update the updated_by column
User::deleting(function($user) {
$user->updated_by = 1;
});
}
}
I have traced the create, update and delete model methods. In every case my event listeners are being picked up and processed.
In the create and update save method though, there is a difference. Both of these methods call the getDirty() method which looks for changed attributes and passes the array to the query builder. This is why that insert or update event works.
The delete method however does not do this check and therefore does not pass those attributes to the builder. Although if you look at the stack during the entire oprtation, $this->model['attributes'] has my changed updated_at attribute! The builder just never uses it.
So I guess my question without re-writing the source how would you go about injecting an attribute into the delete method when using soft deletes. Like in my model example.
The end goal here is to update the updated_by field while doing a soft delete. I am trying to avoid first doing an update of the table then doing a delete.
Upvotes: 0
Views: 2646
Reputation: 469
Just override the method runSoftDelete inside your model
class User extends Model
{
protected function runSoftDelete()
{
$query = $this->newQuery()->where($this->getKeyName(), $this->getKey());
$this->{$this->getDeletedAtColumn()} = $time = $this->freshTimestamp();
$query->update(array($this->getDeletedAtColumn() => $this->fromDateTime($time), 'updated_by' => 1));
}
}
Upvotes: 3
Reputation: 60048
I think the problem is the updating event calls the save()
function after the event, so any changes you do will be included in the save()
call.
The delete event probably does not call the same save()
function - so your changes are being lost.
Try to force the save yourself and see if that works?
User::deleting(function($user) {
$user->updated_by = 1;
$user->save();
});
Upvotes: 1