php - Laravel:正确覆盖 SoftDeletes 特性

标签 php laravel soft-delete

我想制作一个使用 SoftDeletes 的特征命名 SoftDeletesWithStatus这也将更新状态列。我的问题是我想在SoftDeletes中间实现我的代码的功能是这样的:

protected function runSoftDelete() {
    $query = $this->newQueryWithoutScopes()->where($this->getKeyName(), $this->getKey());
    $time = $this->freshTimestamp();
    $columns = [$this->getDeletedAtColumn() => $this->fromDateTime($time)];

   //I want to implement my code here

    $this->{$this->getDeletedAtColumn()} = $time;
    if ($this->timestamps && ! is_null($this->getUpdatedAtColumn())) {
        $this->{$this->getUpdatedAtColumn()} = $time;
        $columns[$this->getUpdatedAtColumn()] = $this->fromDateTime($time);
    }
    $query->update($columns);
}

public function restore() {
    if ($this->fireModelEvent('restoring') === false) {
        return false;
    }
    $this->{$this->getDeletedAtColumn()} = null;

    //I want to implement my code here

    $this->exists = true;
    $result = $this->save();
    $this->fireModelEvent('restored', false);
    return $result;
}

在我的 SoftDeletesWithStatus 中复制粘贴代码是更好的解决方案吗? trait 并在其中实现我的代码?

感谢您的帮助。

最佳答案

JacupoStanchis在我看来,解决方案并不完整。
方法没有处理关系 runSoftDeleterestore的新特性。

假设您有一个简单的关系,例如:Author 1-n Book
工作示例:

$Author->delete();
$Author->restore();

不工作的例子:
$Book->author()->delete();
$Book->author()->restore();

感谢 Xdebug,我可以为“不工作的例子”找到一个解决方案。
顺便提一句。就我而言,需要一个字符串列,因此我可以将唯一约束与删除状态结合使用。所以方法不一样。
app/Traits/SoftDeletes.php
<?php

namespace App\Traits;

use App\Overrides\Eloquent\SoftDeletingScope;

trait SoftDeletes
{
    use \Illuminate\Database\Eloquent\SoftDeletes;

    /**
    * Boot the soft deleting trait for a model.
    *
    * @return void
    */
    public static function bootSoftDeletes()
    {
        static::addGlobalScope(new SoftDeletingScope);
    }

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

        $time = $this->freshTimestamp();

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

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

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

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

        $query->update($columns);
    }

    /**
    * Restore a soft-deleted model instance.
    *
    * @return bool|null
    */
    public function restore()
    {
        // If the restoring event does not return false, we will proceed with this
        // restore operation. Otherwise, we bail out so the developer will stop
        // the restore totally. We will clear the deleted timestamp and save.
        if ($this->fireModelEvent('restoring') === false) {
            return false;
        }

        $this->{$this->getDeletedAtColumn()} = null;
        $this->{$this->getDeletedHashColumn()} = '';

        // Once we have saved the model, we will fire the "restored" event so this
        // developer will do anything they need to after a restore operation is
        // totally finished. Then we will return the result of the save call.
        $this->exists = true;

        $result = $this->save();

        $this->fireModelEvent('restored', false);

        return $result;
    }

    /**
    * Get the name of the "deleted at" column.
    *
    * @return string
    */
    public function getDeletedHashColumn()
    {
        return defined('static::DELETED_HASH') ? static::DELETED_HASH : 'deleted_hash';
    }

}
app/Overrides/Eloquent/SoftDeletingScope.php
<?php

namespace App\Overrides\Eloquent;

use Illuminate\Database\Eloquent;

class SoftDeletingScope extends Eloquent\SoftDeletingScope
{

    /**
    * Extend the query builder with the needed functions.
    *
    * @param  \Illuminate\Database\Eloquent\Builder  $builder
    * @return void
    */
    public function extend(Eloquent\Builder $builder)
    {
        foreach ($this->extensions as $extension) {
            $this->{"add{$extension}"}($builder);
        }

        $builder->onDelete(function (Eloquent\Builder $builder) {
            $deletedAtColumn = $this->getDeletedAtColumn($builder);
            $deletedHashColumn = $builder->getModel()->getDeletedHashColumn();

            return $builder->update([
                $deletedAtColumn => $builder->getModel()->freshTimestampString(),
                $deletedHashColumn => uniqid(),
            ]);
        });
    }

    /**
    * Add the restore extension to the builder.
    *
    * @param  \Illuminate\Database\Eloquent\Builder  $builder
    * @return void
    */
    protected function addRestore(Eloquent\Builder $builder)
    {
        $builder->macro('restore', function (Eloquent\Builder $builder) {
            $builder->withTrashed();

            return $builder->update([
                $builder->getModel()->getDeletedAtColumn() => null,
                $builder->getModel()->getDeletedHashColumn() => '',
            ]);
        });
    }
}

我添加了 bootSoftDeletes添加自定义 SoftDeletingScope 的新特征的方法到全局范围。

关于php - Laravel:正确覆盖 SoftDeletes 特性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50639559/

相关文章:

java - 检查对象是否被引用,以防止在不修改数据库的情况下软删除

php - 打印 boolean 值

php - 多个动态查询范围

php - 物理删除在 laravel5 中启用软删除的模型?

mysql - 如何解决软删除项目的缩放问题?

php - Laravel 如何在提交时将我的身份验证用户 ID 插入到我的数据库中?

php - 如何在 PHP 画廊中构建图像存储

php - 在 PHP 中计算文本差异

php - 像facebook消息系统一样计算时差

mysql - 创建一个子查询别名以在 Laravel 查询生成器中使用它