1
votes

I am building a small application in order to experiment with many-to-many relationships in Laravel 7. This application is about projects and users (many-to-many).

An authenticated user can create new projects. Each project has its own page. On the page of a project, a list is rendered, with the name of each user who is a member to this project, and next to each name, is a button that should remove the specific user/member from that project.

Right now, I'm stuck at the "remove user" function. I do not understand how to get the id of each user on the list, and pass it to the function that will "detach" the many-to-many relationship.

My files are below:

Migrations:

Users_Table:

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->boolean('is_admin')->nullable();
        $table->string('name');
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}

Projects_Table:

public function up()
{
    Schema::create('projects', function (Blueprint $table) {
        //primary key
        $table->bigIncrements('id');

        //foreign keys columns
        $table->unsignedBigInteger('user_id');

        //normal table columns
        $table->string('title')->unique();

        //created_at and updated_at columns
        $table->timestamps();

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

}

Project_Users_Table (Pivot):

public function up()
{
    Schema::create('project_user', function (Blueprint $table) {
        $table->foreignId('project_id')->constrained();
        $table->foreignId('user_id')->constrained();
        $table->timestamps();
    });
}

Models:

User.php:

public function projects()
{
    return $this->belongsToMany('App\Project');
}

Project.php:

protected $fillable = ['name'];

public function members()
{
    return $this->belongsToMany('App\User');
}

public function creator()
{
    return $this->belongsTo('App\User', 'user_id', 'id');
}

View:

<ul>
    @foreach($project->members as $member)
    <li>{{$member->name}}

        <!-- if connected user is admin, show "remove user"  button -->
        @if ( Auth::user()->is_admin == 1 )
        <form class="delete_project_form" method="POST" action="{{url('/projects/'.$project->id.'/remove_user/'.$member->id)}}">
            @csrf
            @method('DELETE')
            <button type="submit" value="Delete">Remove</button>
        </form>
        @endif

    </li>
    @endforeach
</ul>

 

Route:

web.php:

Route::delete('/projects/{project}/remove_user/{member}', 'ProjectController@remove_user');

Controller:

ProjectController.php:

public function remove_user(Project $project)
{
    $user_id = $project->members()->id;
    $project->members()->detach($user_id);
    return redirect('/projects/'.$project->id);
}

I know it obviously is not correct, but with this configuration it gives the following error:

Undefined property: Illuminate\Database\Eloquent\Relations\BelongsToMany::$id

http://localhost/rel_test/public/projects/6/remove_user/2

Can you guys help ? Thank you in advance

1

1 Answers

1
votes

Try this:

public function remove_user(Project $project, User $member)
{
    $project->members()->detach($member->id);
    return redirect('/projects/'.$project->id);
}

Since you're passing two parameters in your route. Therefore, you will get one instance of Project model and one instance of User model. Then just access the relationship and accessing the detach() method with $user->id will do the work. You can detach multiple users by passing array of ids in detach() method, or remove all users from the project by calling detach() with no parameters.

Reference here