Home > Software engineering >  How to get the list of client related through the HasManyThrough relationship
How to get the list of client related through the HasManyThrough relationship

Time:08-03

I have these 3 tables:

clients

id - integer name - string

projects

id - integer client_id - integer name - string

tasks

id - integer project_id - integer name - string

related through the HasManyThrough relationship.

In the client table I have a column relating to the number of tasks relating to the projects of that specific client.

I want that when I click on the number of tasks, I am redirected to the view of the client related tasks. While when I click it shows me all the tasks, but I want, as already specified, the tasks related to the projects of that specific client.

How can I solve this problem?

VIEW:

<tr>
    <th >ID</th>
    <th >Name</th>
    <th >Task</th>
</tr>
@foreach ($clients as $client)
<tr>
    <td>{{ $client->id }}</td>
    <td>{{ $client->name }}</td>
    <td>
        <a href="{{route('task.index'}" >{{ 
      $client->tasks_count }}
        </a>
    </td>
@endforeach

Route:

Route::get('/task/index', [TaskController::class, 'index'])->name('task.index');

TaskController:

public function index()
{
    $tasks = Task::all();
    //dd($tasks);
    return view('task.index', compact('tasks'));
}

Model Client

class Client extends Model
{
    use HasFactory;

    protected $fillable = [
        'name'
    ];

    public function projects()
    {
        return $this->hasMany(Project::class);
    }

    public function tasks()
    {
        return $this->hasManyThrough(Task::class, Project::class);
    }

}

Model Project

class Project extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',     
        'client_id'        
    ];

    public function client()
    {
        return $this->belongsTo(Client::class);
    }

    public function tasks()
    {
        return $this->hasMany(Task::class);
    }
}

Model Task

class Task extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'project_id'
    ];

    public function project()
    {
        return $this->belongsTo(Project::class);
    }
}

CodePudding user response:

Create new route:

Route::get('/client/{client}/tasks', ['as' => 'client.tasks', 'uses' => 'ClientController@tasks'])->name('client.tasks');

Add something like this to your view:

//Not sure if that is a right syntax to bind the id in the route, need to verify 
<a href="{{ route('client.tasks', [$client->id]) }}" >
    {{ $client->tasks_count }}
</a>

Or:

//Route
Route::get('/client/{client}/tasks', [ClientController::class, 'tasks'])->name('client.tasks');

//and view
<a href="{{ URL::to('/client/' . $client->id . '/tasks') }}" >
     {{ $client->tasks_count }}
</a>

And controller:

public function tasks(Client $client)
{
    $tasks = $client->tasks;

    //return your view with tasks associated with this client
}

CodePudding user response:

As you have written

$tasks = Task::all();

All tasks!

You need to pass along the id of the client with the request, preferably with route model binding so that you get a client instance in the controller. Then you can load the tasks or the projects with tasks below them

public function index(Client $client)
{
    $tasks = $client->tasks()->get();
    //dd($tasks);
    return view('task.index', compact('tasks'));
}

or with projects

{
    $projects = $client->projects()->with('tasks')->get();
    
    return view('task.index', compact('projects'));
}

In this second example, you get a collection of projects with the tasks inside, so you can then show a list of projects and a list of tasks for that project

  • Related