Wenn ich eine Zeile mit dieser Syntax lösche:
$user->delete();
Gibt es eine Möglichkeit, eine Art Rückruf anzuhängen, so dass dies z. B. automatisch geschieht:
$this->photo()->delete();
Am besten innerhalb der Modellklasse.
Ich glaube, dies ist ein perfekter Anwendungsfall für eloquente Ereignisse ( http://laravel.com/docs/eloquent#model-events ). Sie können das Ereignis "Löschen" verwenden, um die Bereinigung durchzuführen:
class User extends Eloquent
{
public function photos()
{
return $this->has_many('Photo');
}
// this is a recommended way to declare event handlers
public static function boot() {
parent::boot();
static::deleting(function($user) { // before delete() method call this
$user->photos()->delete();
// do the rest of the cleanup...
});
}
}
Sie sollten wahrscheinlich auch das Ganze in eine Transaktion einfügen, um die referenzielle Integrität sicherzustellen.
first()
der Abfrage hinzufügen, damit ich auf das Modellereignis zugreifen konnte, z. B.User::where('id', '=', $id)->first()->delete();
Quelleforeach($user->photos as $photo)
,$photo->delete()
um sicherzustellen, dass jedes Kind seine Kinder auf allen Ebenen entfernt hat, anstatt nur eines, wie es aus irgendeinem Grund geschah.Photos
hastags
und Sie dasselbe imPhotos
Modell tun (dh beideleting
method :), wird$photo->tags()->delete();
es nie ausgelöst. Aber wenn ich es zu einerfor
Schleife mache und so etwas mache, werdenfor($user->photos as $photo) { $photo->delete(); }
dietags
auch gelöscht! nur zuSie können dies tatsächlich in Ihren Migrationen einrichten:
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
Quelle: http://laravel.com/docs/5.1/migrations#foreign-key-constraints
quelle
Sie können alle zugehörigen Fotos löschen, bevor Sie den Benutzer tatsächlich löschen.
Ich hoffe es hilft.
quelle
$this->photos()->delete()
. Dasphotos()
gibt das Query Builder-Objekt zurück.Beziehung im Benutzermodell:
Datensatz löschen und verwandte:
quelle
Es gibt 3 Lösungsansätze:
1. Verwenden eloquenter Ereignisse beim Modellstart (siehe: https://laravel.com/docs/5.7/eloquent#events )
2. Verwenden von eloquenten Ereignisbeobachtern (siehe: https://laravel.com/docs/5.7/eloquent#observers )
Registrieren Sie den Beobachter in Ihrem AppServiceProvider wie folgt:
Fügen Sie als Nächstes eine Observer-Klasse wie folgt hinzu:
3. Verwenden von Fremdschlüsseleinschränkungen (siehe: https://laravel.com/docs/5.7/migrations#foreign-key-constraints )
quelle
Ab Laravel 5.2 heißt es in der Dokumentation, dass diese Art von Ereignishandlern im AppServiceProvider registriert werden sollten:
Ich nehme sogar an, sie für eine bessere Anwendungsstruktur in separate Klassen anstatt in Schließungen zu verschieben.
quelle
Eloquent::observe()
Methode auch in 5.2 verfügbar und kann über den AppServiceProvider verwendet werden.photos()
, müssen Sie auch vorsichtig sein - dieser Prozess löscht keine Enkelkinder, da Sie keine Modelle laden. Sie müssen eine Schleife durchführenphotos
(beachten Sie, nichtphotos()
) und diedelete()
Methode auf ihnen als Modelle auslösen, um die löschbezogenen Ereignisse auszulösen.Es ist besser, wenn Sie die
delete
Methode dafür überschreiben . Auf diese Weise können Sie DB-Transaktionen in diedelete
Methode selbst integrieren. Wenn Sie die Ereignismethode verwenden, müssen Sie Ihrendelete
Methodenaufruf bei jedem Aufruf mit einer DB-Transaktion abdecken .In Ihrem
User
Modell.quelle
In meinem Fall war es ziemlich einfach, weil meine Datenbanktabellen InnoDB mit Fremdschlüsseln mit Cascade on Delete sind.
Wenn Ihre Fototabelle in diesem Fall eine Fremdschlüsselreferenz für den Benutzer enthält, müssen Sie lediglich das Hotel löschen und die Bereinigung durch die Datenbank durchführen. Die Datenbank löscht alle Fotodatensätze aus den Daten Base.
quelle
Ich würde die Sammlung durchlaufen und alles trennen, bevor ich das Objekt selbst lösche.
Hier ist ein Beispiel:
Ich weiß, dass es nicht automatisch ist, aber es ist sehr einfach.
Ein anderer einfacher Ansatz wäre, dem Modell eine Methode zur Verfügung zu stellen. So was:
Dann können Sie dies einfach dort anrufen, wo Sie es brauchen:
quelle
Oder Sie können dies tun, wenn Sie möchten, nur eine weitere Option:
Hinweis: Wenn Sie nicht die Standard-Laravel-Datenbankverbindung verwenden, müssen Sie folgende Schritte ausführen:
quelle
Um auf die ausgewählte Antwort einzugehen, müssen Sie, wenn Ihre Beziehungen auch untergeordnete Beziehungen haben, die gelöscht werden müssen, zuerst alle untergeordneten Beziehungsdatensätze abrufen und dann die
delete()
Methode aufrufen , damit auch ihre Löschereignisse ordnungsgemäß ausgelöst werden.Sie können dies problemlos mit Nachrichten höherer Ordnung tun .
Sie können die Leistung auch verbessern, indem Sie nur die Spalte Beziehungs-ID abfragen:
quelle
Ja, aber wie @supersan oben in einem Kommentar angegeben hat, wird das Modellereignis nicht ausgelöst, wenn Sie () in einem QueryBuilder löschen (), da wir das Modell selbst nicht laden und dann delete () für dieses Modell aufrufen.
Die Ereignisse werden nur ausgelöst, wenn wir die Löschfunktion für eine Modellinstanz verwenden.
Also sagte dieses Wesen:
Um die Post-Tags beim Löschen des Benutzers zu löschen, müssten wir iterieren
$user->posts
und aufrufen$post->delete()
foreach($user->posts as $post) { $post->delete(); }
-> Dadurch wird das Löschereignis auf Post ausgelöstVS
$user->posts()->delete()
-> Dadurch wird das Löschereignis beim Posten nicht ausgelöst, da das Post-Modell nicht tatsächlich geladen wird (wir führen nur eine SQL wieDELETE * from posts where user_id = $user->id
folgt aus : Daher wird das Post-Modell nicht einmal geladen).quelle
Sie können diese Methode alternativ verwenden.
Was passieren wird, ist, dass wir alle mit der Benutzertabelle verknüpften Tabellen nehmen und die zugehörigen Daten mithilfe von Schleifen löschen
quelle