tables joining with pivot table in laravel

IBMdig :

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

Spholt :

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=20443&siteId=1
Recommended