194

この構文を使用して行を削除すると、次のようになります。

$user->delete();

ある種のコールバックを添付して、たとえばこれを自動的に行う方法はありますか?

$this->photo()->delete();

できればモデルクラス内。

4

17 に答える 17

266

これはEloquentイベント(http://laravel.com/docs/eloquent#model-events)の完璧なユースケースだと思います。「削除」イベントを使用して、クリーンアップを実行できます。

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...
        });
    }
}

参照整合性を確保するために、おそらくすべてをトランザクション内に配置する必要があります。

于 2013-11-20T22:05:56.767 に答える
232

移行で実際にこれを設定できます。

$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

ソース: http: //laravel.com/docs/5.1/migrations#foreign-key-constraints

制約の「削除時」および「更新時」プロパティに必要なアクションを指定することもできます。

$table->foreign('user_id')
      ->references('id')->on('users')
      ->onDelete('cascade');
于 2013-01-05T20:56:24.840 に答える
62

:この回答はLaravel3用に作成されました。したがって、Laravelの最新バージョンではうまく機能する場合と機能しない場合があります。

ユーザーを実際に削除する前に、関連するすべての写真を削除できます。

<?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();
    }
}

それが役に立てば幸い。

于 2013-01-05T17:23:47.043 に答える
40

ユーザーモデルの関係:

public function photos()
{
    return $this->hasMany('Photo');
}

レコードと関連するものを削除します。

$user = User::find($id);

// delete related   
$user->photos()->delete();

$user->delete();
于 2015-01-06T19:13:15.660 に答える
30

これを解決するには、次の3つのアプローチがあります。

1.モデルの起動時にEloquentイベントを使用する(参照: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. Eloquent Event Observersの使用(参照:https ://laravel.com/docs/5.7/eloquent#observers )

AppServiceProviderで、次のようにオブザーバーを登録します。

public function boot()
{
    User::observe(UserObserver::class);
}

次に、次のようなObserverクラスを追加します。

class UserObserver
{
    public function deleting(User $user)
    {
         $user->photos()->delete();
    }
}

3.外部キー制約の使用(参照:https ://laravel.com/docs/5.7/migrations#foreign-key-constraints )

$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
于 2018-09-14T23:02:37.810 に答える
14

Laravel 5.2の時点で、ドキュメントには、これらの種類のイベントハンドラーをAppServiceProviderに登録する必要があると記載されています。

<?php
class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        User::deleting(function ($user) {
            $user->photos()->delete();
        });
    }

アプリケーション構造を改善するために、クロージャではなく別のクラスにそれらを移動することも考えています。

于 2016-05-18T18:15:52.013 に答える
8

このためのメソッドをオーバーライドする方が良いですdeletedeleteこのようにして、メソッド自体にDBトランザクションを組み込むことができます。イベント方式を使用する場合は、deleteメソッドを呼び出すたびに、メソッドの呼び出しをDBトランザクションでカバーする必要があります。

あなたのUserモデルで。

public function delete()
{
    \DB::beginTransaction();

     $this
        ->photo()
        ->delete()
    ;

    $result = parent::delete();

    \DB::commit();

    return $result;
}
于 2019-07-04T05:48:11.747 に答える
6

選択した回答を詳しく説明するために、リレーションシップに削除する必要のある子リレーションシップもある場合は、最初にすべての子リレーションシップレコードを取得してから、delete()メソッドを呼び出して、削除イベントも適切に発生するようにする必要があります。

これは、高次のメッセージを使用して簡単に行うことができます。

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();
        });
    }
}

リレーションシップID列のみをクエリすることで、パフォーマンスを向上させることもできます。

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();
        });
    }
}
于 2019-01-16T20:06:58.810 に答える
4

使用するConstrained()

Laravel 7以降、データベースで関係制約を定義するための新しいメソッドforeignId()とメソッドが利用可能になりました。これらのメソッドでmethodを使用して、関連するレコードを自動的に削除できます。constrained()OnDelete()

古いスタイル

$table->unsignedBigInterer('user_id');

$table->foreign('user_id')
    ->references('id')
    ->on('users')
    ->onDelete('cascade');

新しいスタイル

$table->foreignId('user_id')
      ->constrained()
      ->onDelete('cascade');
于 2021-05-28T08:53:49.820 に答える
2

オブジェクト自体を削除する前に、コレクションを繰り返してすべてを切り離します。

次に例を示します。

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);
    }

自動ではないことは知っていますが、非常に簡単です。

もう1つの簡単なアプローチは、モデルにメソッドを提供することです。このような:

public function detach(){
       try {
            
            if ($this->has('photos')) {
                foreach ($this->photos as $photo) {
    
                    $this->photos()->detach($photo);
                }
            }
           
        } catch (Exception $e) {
            dd($e);
        }
}

次に、必要な場所でこれを呼び出すことができます。

$user->detach();
$user->delete();
于 2018-02-21T20:40:30.863 に答える
1

私の場合、データベーステーブルは削除時にカスケードを使用する外部キーを持つInnoDBであるため、非常に単純でした。

したがって、この場合、写真テーブルにユーザーの外部キー参照が含まれている場合、ホテルを削除するだけで、データベースによってクリーンアップが実行され、データベースはデータからすべての写真レコードを削除します。ベース。

于 2015-01-07T08:11:55.420 に答える
1

この方法はLaravel8で私のために働きました:

public static function boot() {

    parent::boot();
    
    static::deleted(function($item){
        $item->deleted_by = \Auth::id(); // to know who delete item, you can delete this row
        $item->save();  // to know who delete item, you can delete this row
        foreach ($item->photos as $photo){
            $photo->delete();
        }
    });
}

public function photos()
{
    return $this->hasMany('App\Models\Photos');
}

注:この構文での削除は$user->photos()->delete();私には機能しませんでした...

于 2021-11-30T07:28:58.587 に答える
0

または、必要に応じてこれを行うことができます。別のオプションです。

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);
}

デフォルトのlaraveldb接続を使用していない場合は、次のことを行う必要があることに注意してください。

DB::connection('connection_name')->pdo->beginTransaction();
DB::connection('connection_name')->pdo->commit();
DB::connection('connection_name')->pdo->rollBack();
于 2013-02-22T07:47:30.877 に答える
0

モデルの移行を定義するときは、onDeleteカスケードを使用することをお勧めします。これにより、モデルの関係が削除されます。

例えば

 $table->foreign(’user_id’)
  ->references(’id’)->on(’users’)
  ->onDelete(’cascade’);

モデルとその関係を3つまたは4つ以上のネストされた関係に削除する方法を考えている場合は、モデルの関係を再定義することを検討する必要があります。

于 2021-11-30T08:16:22.510 に答える
0

これが完璧な解決策です。

# model

public function order_item_properties()
{
    return $this->hasMany(OrderItemProperty::class, 'order_id', 'id');
}

public function order_variations()
{
    return $this->hasMany(OrderItemVariation::class, 'order_id', 'id');
}

# controller

$order_item = OrderItem::find($request->order_id);

$order_item->order_item_properties()->delete();
$order_item->order_variations()->delete();

$order_item->delete();

return response()->json([
    'message' => 'Deleted',
]);
于 2022-02-16T04:16:35.623 に答える
-1

ええ、しかし@supersanがコメントの上部で述べたように、QueryBuilderでdelete()を実行すると、モデル自体をロードしていないため、モデルイベントは発生しません。次に、そのモデルでdelete()を呼び出します。

モデルインスタンスで削除機能を使用した場合にのみ、イベントが発生します。

だから、この蜂は言った:

if user->hasMany(post)
and if post->hasMany(tags)

ユーザーを削除するときに投稿タグを削除するには、繰り返して$user->posts呼び出す必要があります$post->delete()

foreach($user->posts as $post) { $post->delete(); }->これにより、投稿で削除イベントが発生します

VS

$user->posts()->delete()->実際にはPostモデルをロードしないため、これはPostでdeleteingイベントを発生させません(次のようなSQLのみを実行するDELETE * from posts where user_id = $user->idため、Postモデルもロードされません)

于 2018-09-24T12:38:58.743 に答える
-2

代わりにこの方法を使用できます。

何が起こるかというと、usersテーブルに関連付けられているすべてのテーブルを取得し、ループを使用して関連データを削除します。

$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]);
}
于 2019-04-17T10:53:05.297 に答える