Reputation: 163
I'm working with laravel 5.8 and I have four tables:
clients: id|name|code
tasks: id|name
client_task: id|client_id|task_id
monthlies: id|client_id|task_id|exec_date
Where clients
and tasks
are in many to many relationship and client_task
is the pivot table
The idea is that I want to create a table in html like this
-------------------------------------------
|#|client name|task 1|task 2|task 3|task 4|
-------------------------------------------
|1| client 1 | ☐ | ☐ | /// | /// |
-------------------------------------------
|2| client 2 | /// | ☐ | ☐ | ☑ |
-------------------------------------------
|3| client 3 | ☐ | ☑ | ☑ | /// |
-------------------------------------------
every month I get all the clients and all the tasks and if a client has a task I show a checkbox else I show an empty td
and if I finish a task for a specific client I check this task and insert the client_id
, task_id
and current date exec_date
into monthlies
table.
I right this query:
$clients = DB::table('monthlies as m')
->rightJoin('client_task as clta', function ($join){
$join->on('clta.client_id', '=', 'm.client_id')
->on('clta.task_id', '=', 'm.task_id')
->rightJoin('clients as cl', function ($join){
$join->on('clta.client_id', '=', 'cl.id')->where('cl.category',1);
})
->Join('category_task as cata', function ($join){
$join->on('clta.task_id', '=', 'cata.task_id')
->Join('categories as ca2', 'cata.category_id', '=', 'ca2.id')->where('ca2.type', 1)
->rightJoin('tasks as ta', 'cata.task_id', '=', 'ta.id')->where('ta.period', 1);
});
})
->select('m.*', 'cl.id as client_id', 'cl.name as client_name', 'cl.code as client_code', 'cl.legal_form as client_legal_form', 'ta.id as task_id', 'ta.name as task_name', 'ta.type as task_type', 'ta.period as task_period')
->get();
with this code I get only clients/tasks presents in client_task table
The problem is that I want to show all clients or tasks even if the client has no task attached to and vice versa (not present in client_task
pivot table).
Upvotes: 1
Views: 96
Reputation: 4012
Ok, This may require you to make some changes to your relationships but i think you will see the benefits!
Pivot table attributes & Models
If the only difference between your client_task
and monthlies
table is exec_date
, why not combine the two tables into client_task
?
You can add pivot table attributes to your relationships like so:
Client.php
public function tasks()
{
return $this->belongsToMany(Task::class, 'client_task',`client_id`,'task_id')->withPivot(['exec_date']);
}
Now when you get a Client
's Task
's, you can get the exec_date by using the pivot
attribute ($task->pivot->exec_date
).
You can even go as far as making dedicated Pivot
models as shown in the documentation here
Relationship Existance
You can determine whether a Client
has a given Task
using the whereHas()
function.
Client::whereHas('tasks', function (Builder $query) use ($task) {
$query->where('id', $task->id);
})->get();
Documentation can be found here
Templates
Most of the code for controlling you table will be done in the blade view using simple template logic:
@foreach ($clients as $client)
<tr>
@foreach ($tasks as $task)
<td>
@if ($client->tasks->contains($task))
@if ($client->tasks->where('id', $task->id)->first()->pivot->exec_date)
... checked checkbox ...
@else
... unchecked checkbox ...
@endif
@else
...
@endif
</td>
@endforeach
</tr>
@endforeach
Upvotes: 2