繁体   English   中英

如何在雄辩的榜样上创造条件? (Laravel 5.3)

[英]How to create the conditions on the model of eloquent? (Laravel 5.3)

我在控制器上的删除方法是这样的:

<?php
public function deleteMessage($id, $seller_id, $buyer_id)
{
    //if the seller delete
    if($seller_id == auth()->user->id)
        //const DELETED_AT = 'deleted_by_seller';
    //if the buyer delete
    else($buyer_id == auth()->user->id)
        //const DELETED_AT = 'deleted_by_buyer';

    $result = Message::destroy($id);
    return $result;
}

我的模型是这样的:

<?php
namespace App\Models;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; 
use Jenssegers\Mongodb\Eloquent\HybridRelations;
use Jenssegers\Mongodb\Eloquent\SoftDeletes;
class MessageThread extends Eloquent
{
    use HybridRelations; 
    use SoftDeletes; 
    // const DELETED_AT = 'deleted_by_seller';
    // const DELETED_AT = 'deleted_by_buyer';
    protected $connection = 'mongodb';
    protected $dates = ['deleted_by_seller', 'deleted_by_buyer'];
    protected  $fillable = ['subject', 'information', 'created_at', 'update_at'];
}

我想要这样:

如果卖方删除了该消息,则: const DELETED_AT = 'deleted_by_seller';

如果买家删除了该消息,则: const DELETED_AT = 'deleted_by_buyer';

我该怎么做?

更新:

原始文章指的是我的个人博客

软删除特质

在laravel中,我们通过扩展Illuminate\\Database\\Eloquent\\Model定义自己的模型。 要轻柔地删除模型实例,我们应该在模型中使用Illuminate\\Database\\Eloquent\\SoftDeletes特性。 runSoftDelete()SoftDeletes特性中构建SQL查询的关键函数,获取用于标记记录是否已删除的列,然后使用当前时间戳更新该列。

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

Delete()的过程

当我们在模型上调用delete()函数时会发生什么?

由于我们自己的模型扩展了Illuminate\\Database\\Eloquent\\Model ,我们对此一目了然。 这是delete()函数:

public function delete()
{
    if (is_null($this->getKeyName())) {
        throw new Exception('No primary key defined on model.');
    }

    if ($this->exists) {
        if ($this->fireModelEvent('deleting') === false) {
            return false;
        }

        // Here, we'll touch the owning models, verifying these timestamps get updated
        // for the models. This will allow any caching to get broken on the parents
        // by the timestamp. Then we will go ahead and delete the model instance.
        $this->touchOwners();

        $this->performDeleteOnModel();

        $this->exists = false;

        // Once the model has been deleted, we will fire off the deleted event so that
        // the developers may hook into post-delete operations. We will then return
        // a boolean true as the delete is presumably successful on the database.
        $this->fireModelEvent('deleted', false);

        return true;
    }
}

代码很清楚。 它确保模型具有primaryKey ,并且实例首先存在于数据库中。 然后调用performDeleteOnModel()函数执行删除操作。 要注意!

在这里我们应该知道:

从基类继承的成员被Trait插入的成员覆盖。 优先顺序是当前类中的成员将覆盖Trait方法,而后者又将覆盖继承的方法。

因此,当被调用的performDeleteOnModel()SoftDeletes特性中具有相同名称而在Model类中具有相同名称时,将执行确切的函数。 现在我们回到特征:

protected function performDeleteOnModel()
{
    if ($this->forceDeleting) {
        return $this->newQueryWithoutScopes()->where($this->getKeyName(), $this->getKey())->forceDelete();
    }

    return $this->runSoftDelete();
}

好吧,它调用了我们一开始就谈到的runSoftDelete() 这是软检测的过程。

获取问题

DELETED_AT在删除时希望使用不同的DELETED_AT列。 仅通过重写getDeletedAtColumn()来保持软删除机制正常工作还需要很多。 为什么删除的模型即使被轻柔地删除仍然仍然在结果中?

构造Model类时,它将通过调用特性的boot[TraitName]方法来启动特性。 因此,这里是bootSoftDelete()方法。

protected static function bootTraits()
{
    foreach (class_uses_recursive(get_called_class()) as $trait) {
        if (method_exists(get_called_class(), $method = 'boot'.class_basename($trait))) {
            forward_static_call([get_called_class(), $method]);
        }
    }
}

现在,让我们再次关注SoftDeletes特性。

public static function bootSoftDeletes()
{
    static::addGlobalScope(new SoftDeletingScope);
}

在这里,特征通过调用static::addGlobalScope()注册一个具有apply()方法的SoftDeletingScope类。 该方法位于Model类中,将其存储到$globalScopes数组中。

public static function addGlobalScope(ScopeInterface $scope)
{
    static::$globalScopes[get_called_class()][get_class($scope)] = $scope;
}

当在模型上构建查询时,将自动调用applyGlobalScopes()方法,一个接一个地访问$globalScopes数组中的实例,然后调用它们的apply()方法。

public function applyGlobalScopes($builder)
{
    foreach ($this->getGlobalScopes() as $scope) {
        $scope->apply($builder, $this);
    }

    return $builder;
}

我们现在将揭开问题的面纱。 SoftDeletingScope类中:

public function apply(Builder $builder, Model $model)
{
    $builder->whereNull($model->getQualifiedDeletedAtColumn());

    $this->extend($builder);
}

它将在每个查询上添加一个约束,以选择DELETED_AT空的那些记录。 这就是SoftDeletes的秘密。

动态DELETED_AT列

首先,我需要重申,我不建议您使用动态DELETED_AT列。

为了解决动态DELETED_AT列的提问者问题,您需要使用此类apply()函数实现自己的SoftDeletingScope类:

public function apply(Builder $builder, Model $model)
{
    $builder->where(function ($query){
        $query->where('DELETED_AT_COLUMN_1',null)->orWhere('DELETED_AT_COLUMN_2',null);
    });

    $this->extend($builder);
}

然后用它覆盖bootSoftDeletes()

public static function bootSoftDeletes()
{
    static::addGlobalScope(new YourOwnSoftDeletingScope);
}

原始答案:

您不能在运行时更改const变量的值。 因此,您需要手动分配CREATED_AT的值。

首先,我建议这不是理想的数据库结构。 您应该有两列:Deleted_by和Deleted_at,而不是包括Deleted_by_seller和Deleted_by_buyer,其中之一始终为null。

如果您仍然想继续使用现有的数据库结构(如@William指出的那样),请尝试以下操作:

在模型类中,添加以下内容:

 protected $deletedAtCol = "deleted_at";

 /**
 * Get the name of the "deleted at" column.
 *
 * @return string
 */
public function getDeletedAtColumn()
{
    return $this->deletedAtCol;
}

/**
 * Set the name of the "deleted at" column.
 * @param string $colName
 * @return string
 */
public function setDeletedAtColumn($colName)
{
    $this->deletedAtCol = $colName;
}

然后在您的控制器中添加以下内容:

public function deleteMessage($id, $seller_id, $buyer_id)
{
    $message = Message::findOrFail($id); 
    //if the seller delete
    if($seller_id == auth()->user->id)
        $message->setDeletedAtCol("deleted_by_seller");
    //if the buyer delete
    else($buyer_id == auth()->user->id)
        $message->setDeletedAtCol("deleted_by_buyer");

    return $message->delete();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM