更新:
オリジナルの記事はlaravelでは私のpersonal blog
SoftDeletes形質
を意味し、我々はIlluminate\Database\Eloquent\Model
を拡張することにより、当社の独自のモデルを定義します。モデルインスタンスを柔らかく削除するには、モデルでIlluminate\Database\Eloquent\SoftDeletes
の特性を使用する必要があります。 runSoftDelete()
は、SoftDeletes
の主要な機能であり、レコードが削除されたかどうかを示すために使用される列を取得し、現在のタイムスタンプで列を更新します。
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()
関数を呼び出します。注意が必要です!
ここで私たちが知っている必要があります。
Anは基本クラスからメンバを継承は形質によって挿入されたメンバーによって上書きされます。優先順位は、現在のクラスのメンバーがTraitメソッドをオーバーライドし、継承されたメソッドをオーバーライドすることです。
呼ばperformDeleteOnModel()
が同じSoftDeletes
特性に名前はなくModel
クラスの1を有するものであるときに、正確な関数が実行されます。そして今、我々は形質に引き返す:
protected function performDeleteOnModel()
{
if ($this->forceDeleting) {
return $this->newQueryWithoutScopes()->where($this->getKeyName(), $this->getKey())->forceDelete();
}
return $this->runSoftDelete();
}
まあ、それは我々が最初に話しましたrunSoftDelete()
を呼び出します。そして、これは柔らかいdetetionの手順です。アスカー
の取得に
問題は、削除時に異なる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
列nullであるそれらのレコードを選択するために、すべてのクエリに制約を追加します。そしてこれは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);
}
そしてそれ
public static function bootSoftDeletes()
{
static::addGlobalScope(new YourOwnSoftDeletingScope);
}
オリジナルでbootSoftDeletes()
をオーバライド答え:
の値を変更することはできません。実行時の変数。したがって、CREATED_AT
の値を手動で割り当てる必要があります。
あなたは正しい答えを持っているようです。やってみます。ありがとう –
あなたの方法を使用する場合、それは2つの列:deleted_byとdeleted_atを使用しています。 deleted_byをどのように埋めることができますか?削除された場合は、すでに自動的に入力されています –
その方法の場合、モデルイベントを使用することができます:https://laravel.com/docs/5.4/eloquent#events – Paras