关于软删除问题

需求:软删除时,记录一下删除的操作用户是谁,
所以设计数据表的时候,增加字段 deleted_by , deleted_at
发现执行 Book::destroy (1); 只修改了 deleted_at。这时候我想增加一个模型事件

    public static function boot()
    {
        parent::boot();
        static::deleting(function ($model) {
                $model->deleted_by = Auth::id();
        });
    }

发现不生效。
这时候,我手动建了一个 Traits。其他代码一样,只是 runSoftDelete 加一行代码.. 然后我的模型 use App\Traits\SoftDeletes;(我自定义的)

代码已被折叠,点此展开

有没有好一点的方法?

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 7

关于 Laravel 的的软删除确实有些瑕疵,有时候也不是很方便。
像这个也只能自定义 SoftDeletes 来处理了,但我想提示两点

  1. 可以复用 Illuminate\Database\Eloquent\SoftDeletes 这个 trait
  2. 解决你自定义 SoftDeletes 后部分关联模型的软删除字段处理失效的问题

如在 Illuminate\Database\Eloquent\Relations\HasManyThrough 中会判断这个 trait

<?php

namespace Illuminate\Database\Eloquent\Relations;

...
use Illuminate\Database\Eloquent\SoftDeletes;

class HasManyThrough extends Relation
{
     /**
     * Determine whether "through" parent of the relation uses Soft Deletes.
     *
     * @return bool
     */
    public function throughParentSoftDeletes()
    {
        return in_array(SoftDeletes::class, class_uses_recursive($this->throughParent));
    }
}

代码如下

<?php
namespace App\Traits;

use Illuminate\Database\Eloquent\SoftDeletes as OriginSoftDeletes;

/**
 * 自定义软删除,增加一个删除用户ID.
 */
trait SoftDeletes
{
    use OriginSoftDeletes;

    /**
     * Perform the actual delete query on this model instance.
     */
    protected function runSoftDelete()
    {
        $query = $this->newModelQuery()->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);
        }

        //删除时候,增加用户ID. 也可以在 Model 自定义模型事件来处理这个或更多字段
        $columns['deleted_by'] = Auth::id();

        $query->update($columns);
    }
}
6年前 评论

是否可以在 updating 事件中,尝试使用 isDirty 方法,来判断当前是否是软删除操作?

6年前 评论

deleting 替换成 deleted 试试?

5年前 评论
幽弥狂

为啥不用 Observer 呢?
示例地址

5年前 评论

改下 SoftDeletes 里的 runSoftDelete 方法即可:

    protected function runSoftDelete()
    {
        $query = $this->setKeysForSaveQuery($this->newModelQuery());

        $time = $this->freshTimestamp();

        $columns = $this->getDirty();    // 把这之前已更新的字段取过来
        $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);
    }
class UserDeleting
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(&$object)
    {
        $object->deleted_by = Auth::id();
    }
}
5年前 评论

请问下作者,我使用 Laravel 6runSoftDelete 增加参数没有作用

4年前 评论