[英]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()
函数时会发生什么?
由于我们自己的模型扩展了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
列的提问者问题,您需要使用此类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.