Laravel Realizes Data Soft Deletion Function

  • 2021-12-21 04:15:23
  • OfStack

For any 1 model, if you need to use the soft delete function, you need to use it in the model Illuminate\Database\Eloquent\SoftDeletes This trait. The soft delete function needs to realize the following functions:

1. The model performs deletion operation, only marks deletion, and does not perform real data deletion

2. Automatically filter data marked for deletion when querying

3. You can set whether to query deleted data or not. You can set to query only deleted data

4. Deleted data can be recovered

Implementation of Model Soft Delete Function


Illuminate\Database\Eloquent\Model  Medium delete Method source code :

public function delete()
{
 if (is_null($this->getKeyName())) {
  throw new Exception('No primary key defined on model.');
 }
 if (! $this->exists) {
  return;
 }
 if ($this->fireModelEvent('deleting') === false) {
  return false;
 }
 $this->touchOwners();
 $this->performDeleteOnModel();
 $this->fireModelEvent('deleted', false);
 return true;
}
protected function performDeleteOnModel()
{
 $this->setKeysForSaveQuery($this->newModelQuery())
 ->delete();
 $this->exists = false;
}

Because SoftDeletes trait is used in the subclass,  SoftDeletes Adj.  performDeleteOnModel Method overrides the method of the parent class, and finally passes the  runSoftDelete Method updates the deletion flag.


protected function performDeleteOnModel()
{
 if ($this->forceDeleting) {
  $this->exists = false;
  return $this->newModelQuery()->where(
    $this->getKeyName(), $this->getKey()
  )->forceDelete();
 }
 return $this->runSoftDelete();
}

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);
 }
 $query->update($columns);
}

Model Query Filter Delete Data

Allowable in Laravel in Model static::addGlobalScope Method to add a global Scope. In this way, you can add 1 global condition to the query condition. The filtering of soft delete data in Laravel is also implemented in this way.

SoftDeletes trait is added Illuminate\Database\Eloquent\SoftDeletingScope Global Scope. And in SoftDeletingScope, the query automatically filters deleted data and specifies the function of querying deleted data.


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

Soft deletion of remote associated data

The role of Scope lies only in the current model and the operation of the associated model. If it is a remote association, additional processing is required. The Laravel remote association is implemented through hasManyThrough. There are two places involved in the query of soft deletion.


protected function performJoin(Builder $query = null)
{
 $query = $query ?: $this->query;
 $farKey = $this->getQualifiedFarKeyName();
 $query->join($this->throughParent->getTable(), $this->getQualifiedParentKeyName(), '=', $farKey);
 if ($this->throughParentSoftDeletes()) {
  $query->whereNull(
   $this->throughParent->getQualifiedDeletedAtColumn()
  );
 }
}

public function throughParentSoftDeletes()
{
 return in_array(SoftDeletes::class, class_uses_recursive(
  get_class($this->throughParent)
 ));
}
public function getRelationExistenceQueryForSelfRelation(Builder $query, Builder $parentQuery, $columns = ['*'])
{
 $query->from( $query->getModel()->getTable().' as '
  .$hash = $this->getRelationCountHash()
 );
 $query->join($this->throughParent->getTable(), 
  $this->getQualifiedParentKeyName(), '=', $hash.'.'.$this->secondLocalKey
 );
 if ($this->throughParentSoftDeletes()) {
  $query->whereNull($this->throughParent->getQualifiedDeletedAtColumn());
 }
 $query->getModel()->setTable($hash);
 return $query->select($columns)->whereColumn(
  $parentQuery->getQuery()->from.'.'.$query->getModel()->getKeyName(), '=', $this->getQualifiedFirstKeyName()
 );
}

In performJoin, the remote model is associated through the intermediate model, which will be based on the throughParentSoftDeletes Judge whether there is soft deletion in the intermediate model, and if there is soft deletion, filter out the deleted data of the intermediate model.

The above is the general logic of Laravel to realize soft deletion. There is one detail here. The soft deletion mark in Laravel is a field in time format, and the default is delete_at . Whether the data is deleted is judged by whether it is null or not.

However, sometimes, a shaped field is used in the project to mark whether the data is deleted or not. In such a scenario, the soft deletion of Laravel needs to be modified before it can be realized.

The main programs are:

1. Customize SoftDeletes trait, modify field names, modify update and delete tag operations;

2. Modify query criteria by customizing SoftDeletingScope

3. Custom HasRelationships trait, override newHasManyThrough method in custom HasRelationships, instantiate custom HasManyThrough object

Summarize

The above is this site to introduce you to Laravel data soft deletion function, I hope to help you, if you have any questions welcome to leave me a message, this site will reply to you in time!


Related articles: