Bu sözdizimini kullanarak bir satırı sildiğimde:
$user->delete();
Bir tür geri arama eklemenin bir yolu var mı, örneğin bunu otomatik olarak yapar:
$this->photo()->delete();
Tercihen model sınıfı içinde.
Bu sözdizimini kullanarak bir satırı sildiğimde:
$user->delete();
Bir tür geri arama eklemenin bir yolu var mı, örneğin bunu otomatik olarak yapar:
$this->photo()->delete();
Tercihen model sınıfı içinde.
Yanıtlar:
Bunun Eloquent olayları için mükemmel bir kullanım örneği olduğuna inanıyorum ( http://laravel.com/docs/eloquent#model-events ). Temizleme işlemini yapmak için "silme" etkinliğini kullanabilirsiniz:
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...
});
}
}
Referans bütünlüğünü sağlamak için muhtemelen her şeyi bir işlemin içine koymalısınız.
foreach($user->photos as $photo), sonra eklemek zorunda kaldım , o zaman $photo->delete()her çocuğun bir sebepten dolayı olduğu gibi tek bir çocuk yerine tüm seviyelerinde çocuklarının kaldırıldığından emin olmak için.
Photosvardır tagsve içinde aynı şeyi Photos(üzerinde yani modeli deletingyöntemiyle: $photo->tags()->delete();) o tetiği geçmez. Bunun bir hale Ama eğer fordöngü ve böyle bir şey yapmak for($user->photos as $photo) { $photo->delete(); }sonra tagsda silinir! sadece FYI
Bunu aslında taşıma işlemlerinizde ayarlayabilirsiniz:
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
Kaynak: http://laravel.com/docs/5.1/migrations#foreign-key-constraints
Kısıtlamanın "silindiğinde" ve "güncellenirken" özellikleri için istediğiniz eylemi de belirtebilirsiniz:
$table->foreign('user_id') ->references('id')->on('users') ->onDelete('cascade');
Not : Bu cevap Laravel 3 için yazılmıştır . Bu nedenle Laravel'in daha yeni sürümünde iyi olabilir veya olmayabilir.
Kullanıcıyı gerçekten silmeden önce ilgili tüm fotoğrafları silebilirsiniz.
<?php
class User extends Eloquent
{
public function photos()
{
return $this->has_many('Photo');
}
public function delete()
{
// delete all related photos
$this->photos()->delete();
// as suggested by Dirk in comment,
// it's an uglier alternative, but faster
// Photo::where("user_id", $this->id)->delete()
// delete the user
return parent::delete();
}
}
Umarım yardımcı olur.
$this->photos()->delete(). photos()Sorgu oluşturucu nesnesini geri gönderir.
Kullanıcı modelinde ilişki:
public function photos()
{
return $this->hasMany('Photo');
}
Kayıt silme ve ilgili:
$user = User::find($id);
// delete related
$user->photos()->delete();
$user->delete();
Bunu çözmek için 3 yaklaşım vardır:
1. Model Önyüklemesinde Eloquent Olayları Kullanma (ref: https://laravel.com/docs/5.7/eloquent#events )
class User extends Eloquent
{
public static function boot() {
parent::boot();
static::deleting(function($user) {
$user->photos()->delete();
});
}
}
2. Olağanüstü Olay Gözlemcilerini Kullanma (ref: https://laravel.com/docs/5.7/eloquent#observers )
AppServiceProvider'ınızda gözlemciyi şu şekilde kaydedin:
public function boot()
{
User::observe(UserObserver::class);
}
Sonra şöyle bir Observer sınıfı ekleyin:
class UserObserver
{
public function deleting(User $user)
{
$user->photos()->delete();
}
}
3. Yabancı Anahtar Kısıtlamalarını Kullanma (ref: https://laravel.com/docs/5.7/migrations#foreign-key-constraints )
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
Laravel 5.2 itibariyle, belgeler bu tür olay işleyicilerin AppServiceProvider'da kaydedilmesi gerektiğini belirtir:
<?php
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
User::deleting(function ($user) {
$user->photos()->delete();
});
}
Hatta onları daha iyi uygulama yapısı için kapaklar yerine ayrı sınıflara taşımayı düşünürüm.
photos(), ayrıca dikkatli olmak gerekir - bu işlem olacak değil sen modellerini silme torun yüklenmemesi çünkü. Silme ile ilgili olayları tetiklemek için döngü üzerine photos(not not not over photos()) ve delete()yöntemi yöntem olarak tetiklemeniz gerekir.
Bunun için deleteyöntemi geçersiz kılmanız daha iyidir . Bu şekilde, DB işlemlerini deleteyöntemin içine dahil edebilirsiniz . Olay yolunu kullanırsanız, deleteher çağrışınızda yöntem çağrınızı bir DB işlemiyle örtmeniz gerekir.
Sizin de Usermodelin.
public function delete()
{
\DB::beginTransaction();
$this
->photo()
->delete()
;
$result = parent::delete();
\DB::commit();
return $result;
}
Benim durumumda oldukça basitti çünkü veritabanı tablolarım InnoDB ile Cascade on Delete tuşlarına sahip.
Bu durumda, fotoğraf tablonuz kullanıcı için yapmanız gereken tek şey yabancı bir anahtar referansı içeriyorsa oteli silmek ve temizleme Veri Tabanı tarafından yapılacaksa, veri tabanı tüm fotoğraf kayıtlarını verilerden silecektir tabanı.
Nesnenin kendisini silmeden önce her şeyi ayıran koleksiyonda yineleme yapardım.
İşte bir örnek:
try {
$user = user::findOrFail($id);
if ($user->has('photos')) {
foreach ($user->photos as $photo) {
$user->photos()->detach($photo);
}
}
$user->delete();
return 'User deleted';
} catch (Exception $e) {
dd($e);
}
Otomatik olmadığını biliyorum ama çok basit.
Başka bir basit yaklaşım, modele bir yöntem sağlamak olacaktır. Bunun gibi:
public function detach(){
try {
if ($this->has('photos')) {
foreach ($this->photos as $photo) {
$this->photos()->detach($photo);
}
}
} catch (Exception $e) {
dd($e);
}
}
O zaman bunu ihtiyacınız olan yerde arayabilirsiniz:
$user->detach();
$user->delete();
Ya da isterseniz, başka bir seçenek yapabilirsiniz:
try {
DB::connection()->pdo->beginTransaction();
$photos = Photo::where('user_id', '=', $user_id)->delete(); // Delete all photos for user
$user = Geofence::where('id', '=', $user_id)->delete(); // Delete users
DB::connection()->pdo->commit();
}catch(\Laravel\Database\Exception $e) {
DB::connection()->pdo->rollBack();
Log::exception($e);
}
Varsayılan laravel db bağlantısını kullanmıyorsanız, aşağıdakileri yapmanız gerektiğini unutmayın:
DB::connection('connection_name')->pdo->beginTransaction();
DB::connection('connection_name')->pdo->commit();
DB::connection('connection_name')->pdo->rollBack();
Seçilen cevabı ayrıntılı olarak açıklamak için, ilişkilerinizde de silinmesi gereken alt ilişkiler varsa, önce tüm alt ilişki kayıtlarını almanız ve ardından delete() silme olaylarının da düzgün bir şekilde yöntemi gerekir.
Bunu daha üst düzey mesajlarla kolayca yapabilirsiniz .
class User extends Eloquent
{
/**
* The "booting" method of the model.
*
* @return void
*/
public static function boot() {
parent::boot();
static::deleting(function($user) {
$user->photos()->get()->each->delete();
});
}
}
Ayrıca yalnızca ilişki kimliği sütununu sorgulayarak performansı artırabilirsiniz:
class User extends Eloquent
{
/**
* The "booting" method of the model.
*
* @return void
*/
public static function boot() {
parent::boot();
static::deleting(function($user) {
$user->photos()->get(['id'])->each->delete();
});
}
}
evet, ancak bir yorumda @supersan'ın yukarıda belirttiği gibi, bir QueryBuilder'da () silerseniz, model olayı tetiklenmeyecektir, çünkü modelin kendisini yüklemiyoruz, sonra bu modelde delete () çağırıyoruz.
Olaylar yalnızca bir Model Eşgörünümünde silme işlevini kullanırsak tetiklenir.
Yani, bu arı şöyle dedi:
if user->hasMany(post)
and if post->hasMany(tags)
kullanıcıyı silerken posta etiketlerini silmek için tekrar tekrar aramamız $user->postsve$post->delete()
foreach($user->posts as $post) { $post->delete(); } -> Bu, Post'taki silme etkinliğini tetikler
VS
$user->posts()->delete()-> Bu, Post Modelini yüklemediğimiz için silme olayını gönderilmeyecek (yalnızca aşağıdaki gibi bir SQL çalıştırıyoruz: DELETE * from posts where user_id = $user->idve böylece Post modeli bile yüklenmiyor)
Bu yöntemi alternatif olarak kullanabilirsiniz.
Ne olacağı, kullanıcı tablosuyla ilişkili tüm tabloları alıp ilgili verileri döngü kullanarak silmemizdir.
$tables = DB::select("
SELECT
TABLE_NAME,
COLUMN_NAME,
CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME = 'users'
");
foreach($tables as $table){
$table_name = $table->TABLE_NAME;
$column_name = $table->COLUMN_NAME;
DB::delete("delete from $table_name where $column_name = ?", [$id]);
}
first()erişmek için sorguya eklemek gerekiyordu örneğin KaynakUser::where('id', '=', $id)->first()->delete();