Crack_David
Crack_David

Reputation: 2843

Laravel many-to-many relationship - detach all and delete if nothing else attached

In laravel I got a many-to-many relation between nodes and users:

Nodes

    public function up()
    {
        Schema::create('nodes', function (Blueprint $table) {
            $table->bigIncrements('id')->index();

            $table->string('syncState')->nullable();
            $table->integer('jsonRpcPort')->nullable();
            $table->string('addr')->unique()->index();
            $table->BigInteger('height')->nullable();
            $table->string('nodeId')->nullable();
            $table->string('publicKey')->nullable()->index();
            $table->integer('websocketPort')->nullable();
            $table->integer('relayMessageCount')->nullable();
            $table->integer('sversion')->nullable();
            $table->string('version')->nullable();

            $table->timestamps();
        });
    }

In Node-Model:

    public function users()
    {
        return $this->belongsToMany('App\User')->withPivot('hostname', 'label', 'notified_offline', 'notified_outdated', 'notified_stuck');
    }

Users

        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');

            $table->string('name');
            $table->string('email')->unique();
            $table->boolean('verified')->default(false);
            $table->string('password');

            $table->rememberToken();
            $table->timestamps();
        });

In User-Model:

    public function nodes()
    {
        return $this->belongsToMany('App\Node')->withPivot('hostname', 'label', 'notified_offline', 'notified_outdated', 'notified_stuck');
    }

Node_user

    {
        Schema::create('node_user', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('user_id');
            $table->unsignedBigInteger('node_id');

            $table->string('hostname')->nullable();
            $table->string('label')->nullable();
            $table->timestamp('notified_offline')->nullable();
            $table->timestamp('notified_outdated')->nullable();
            $table->timestamp('notified_stuck')->nullable();
            $table->timestamps();

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

            $table->foreign('node_id')
            ->references('id')->on('nodes')
            ->onDelete('cascade');
        });
    }

Now if I call $user->nodes()->detach(); to detach all nodes from a user I also want that - if no other user is attached to - these node should also be removed from the database.

How do I archieve that? I'm using postgresql btw.

Upvotes: 1

Views: 1888

Answers (1)

Watercayman
Watercayman

Reputation: 8178

Probably easiest is to just do a check after calling the detach(). Laravel is a little wishy-washy with observers for pivots, so if you have the detach() in just one method, perhaps something like the below code after the detach() action.

How about just checking the nodes in general that don't have a user, and then deleting them:

$nodesToDelete= Node::doesntHave('users')->pluck('id')->toArray();
Node::destroy($nodesToDelete);

If you only want to delete those that were just unattached, collect those 'to-be-detached' ids in an array before you detach them, and add to a whereIn clause in the above 1st line of code for only those nodes.

Upvotes: 1

Related Questions