My delete method on the controller is like this :
<?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;
}
My model is like this :
<?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'];
}
I wanted to like this :
if the seller delete the message then : const DELETED_AT = 'deleted_by_seller';
if the buyer delete the message then : const DELETED_AT = 'deleted_by_buyer';
How can I do it?
Update:
the original article refers my personal blog
In laravel, we define our own model by extending Illuminate\Database\Eloquent\Model
. To delete a model instance softly, we should use Illuminate\Database\Eloquent\SoftDeletes
trait in our model. runSoftDelete()
is the key function in SoftDeletes
trait building a sql query, getting the column which is used to mark whether the record has been deleted or not and then update the column with current timestamps.
protected function runSoftDelete()
{
$query = $this->newQueryWithoutScopes()->where($this->getKeyName(), $this->getKey());
$this->{$this->getDeletedAtColumn()} = $time = $this->freshTimestamp();
$query->update([$this->getDeletedAtColumn() => $this->fromDateTime($time)]);
}
What happens when we call delete()
function on a model?
Since our own model extends the Illuminate\Database\Eloquent\Model
, we take a glance at it. Here is the delete()
function:
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;
}
}
The code is clear. It ensures the model has a primaryKey
and the instance exists in database firstly. Then call performDeleteOnModel()
function to perform deletion opreation. Attention should be paid!
Here we should know:
An inherited member from a base class is overridden by a member inserted by a Trait. The precedence order is that members from the current class override Trait methods, which in turn override inherited methods.
So the exact function executes when performDeleteOnModel()
called is the one with the same name in SoftDeletes
trait but not the one in Model
class. And now we turn back to the trait:
protected function performDeleteOnModel()
{
if ($this->forceDeleting) {
return $this->newQueryWithoutScopes()->where($this->getKeyName(), $this->getKey())->forceDelete();
}
return $this->runSoftDelete();
}
Well, it calls runSoftDelete()
we have talked about in the beginning. And this is procedure of soft detetion.
The asker wants to use different DELETED_AT
columns when deleting. It leaves much to be desired to keep soft deletion mechanism working well by overridding getDeletedAtColumn()
only. Why the deleted models are still in results even if they have been deleted softly?
When Model
class is constructed, it will boot traits by calling their their boot[TraitName]
method. Thus here is bootSoftDelete()
method.
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]);
}
}
}
Now let's pour attention on the SoftDeletes
trait again.
public static function bootSoftDeletes()
{
static::addGlobalScope(new SoftDeletingScope);
}
Here the trait registers a SoftDeletingScope
class having an apply()
method by calling static::addGlobalScope()
. The method, which located in Model
class stores it into $globalScopes
array.
public static function addGlobalScope(ScopeInterface $scope)
{
static::$globalScopes[get_called_class()][get_class($scope)] = $scope;
}
When a query is built on a model, applyGlobalScopes()
method will be called automatically, visiting instances in $globalScopes
array one by one and call their apply()
method.
public function applyGlobalScopes($builder)
{
foreach ($this->getGlobalScopes() as $scope) {
$scope->apply($builder, $this);
}
return $builder;
}
We will lift the veil of problem now. In SoftDeletingScope
class:
public function apply(Builder $builder, Model $model)
{
$builder->whereNull($model->getQualifiedDeletedAtColumn());
$this->extend($builder);
}
It will add a constraint on every query to select those records whose DELETED_AT
column is null. And this is the secret of SoftDeletes
.
Firstly, I need to reaffirm that I don't recommend such behaviour of using dynamic DELETED_AT
column.
In order to solve the asker's problems of dynamic DELETED_AT
column, you need to implement your own SoftDeletingScope
class with such apply()
function:
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);
}
And then overide bootSoftDeletes()
with it
public static function bootSoftDeletes()
{
static::addGlobalScope(new YourOwnSoftDeletingScope);
}
Original answer:
You can't change the value of a const
variable in the running time. So you need to assign the value of CREATED_AT
manually.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With