关于软删除问题

需求:软删除时,记录一下删除的操作用户是谁,
所以设计数据表的时候,增加字段 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;(我自定义的)

代码已被折叠,点此展开

有没有好一点的方法?

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 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 试试?

6年前 评论
幽弥狂

为啥不用 Observer 呢?
示例地址

6年前 评论

改下 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();
    }
}
6年前 评论

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

5年前 评论