phplaravellaravel-5where-clausepluck

Laravel 5.4 pluck, where


I'm working on an assignment system for radio newscasts. Trying to return a view of all assignments for a particular newscast, and I'm stymied.

Tables
users table

 id | name
 ---|-------
  1 | Admin
  2 | Susan
  3 | Ed
  4 | Jen

newscasts table

 id | forStation_id | name
 ---|---------------|-----
  1 |       1       | AM
  2 |       1       | PM
  3 |       2       | Sports

stations table

 id | calls
 ---| -----
  1 | JNDV
  2 | YXWQ

assignments table

 id | anchorId | newscastId |  startDate  |   endDate   | isTemp
 ---|----------|------------|-------------|-------------|--------
  1 |     2    |     1      | 01 May 2017 | 31 Dec 2999 |
  2 |     3    |     1      | 02 May 2017 | 06 May 2017 |  True
  3 |     4    |     2      | 01 Apr 2017 | 31 Dec 2999 |
  4 |     3    |     3      | 01 Apr 2017 | 28 Apr 2017 |

(part of) Assignment model

public function anchor()
{
    return $this->belongsTo(User::class, 'anchor_id')->withTrashed();
}

public function cast()
{
    return $this->belongsTo(Newscast::class, 'cast_id')->withTrashed();
}

(part of) Newscast model

public function for_station()
{
    return $this->belongsTo(Station::class, 'for_station_id')->withTrashed();
}

function getNameInputStationAttribute() {
    return $this->for_station->calls . "-" . $this->name_input;
}

(part of) Assignment controller

/**
 * Display all Assignments for one input name.
 *
 * @param  int  $name
 * @return \Illuminate\Http\Response
 */
public function showAssignmentsByCastName($castName)
{
    if (! Gate::allows('assignment_view')) {
        return abort(403);
    }
    $relations = [
        'anchors' => \App\User::get()->pluck('name', 'id'),
        'casts' =>  \App\Newscast::with('for_station')->get()->pluck('name_input_station', 'id'),
        'assignments' => \App\Assignment::with('cast')->get(),
    ];

dump($relations);

return view('assign.list', compact('castName') +$relations);
}

As I'd expect, this code returns the full collection of assignments.

Output

  Anchor  | Cast Name   | Start Date  |   End Date
 ---------|-------------|-------------|-------------
  Susan   | JNDV-AM     | 01 May 2017 | 31 Dec 2999
  Ed      | JNDV-AM     | 02 May 2017 | 06 May 2017
  Jen     | JNDV-PM     | 01 Apr 2017 | 31 Dec 2999
  Ed      | YXWQ-Sports | 01 Apr 2017 | 28 Apr 2017

I've tried several ways to limit the assignments to only one newscastId, thus far without success.

Desired Output for /assignment/list/JNDV-AM on 01 May 2017

  Anchor  | Cast Name   | Start Date  |   End Date
 ---------|-------------|-------------|-------------
  Susan   | JNDV-AM     | 01 May 2017 | 31 Dec 2999
  Ed      | JNDV-AM     | 02 May 2017 | 06 May 2017

The shorter-term assignment is a temporary one (isTemp=True). During the days it is valid, it should be listed on top.

Desired Output for /assignment/list/JNDV-AM on 02 May 2017 through 06 May 2017

  Anchor  | Cast Name   | Start Date  |   End Date
 ---------|-------------|-------------|-------------
  Ed      | JNDV-AM     | 02 May 2017 | 06 May 2017
  Susan   | JNDV-AM     | 01 May 2017 | 31 Dec 2999

I'm modifying code produced by an admin panel generator tool. It seems to me that querying for all users and all casts is not the most efficient way to go about it. I'd think, since I'm looking for only the current & future assignments for one newscast, that the anchors and casts relations should be filtered.

Basic question What changes should I make to
'assignments' => \App\Assignment::with('cast')->get(),
to get only the assignments for JNDV-AM (newscastId = 1)?

Advanced Question How do you recommend changing relations to return only the current and future assignments for JNDV-AM, today's assignment first, with the fewest queries possible?


Solution

  • Here is the working code I came up with:

    (part of) Assignments controller

    public function showAssignmentsByCastName($calls, $name_input)
    {
        if (!Gate::allows('assignment_view')) {
            return abort(403);
        }
    
        $castName = strtoupper($calls). "-" . $name_input;
        $station_id = \App\Station::where('calls', $calls)->get();
        $station = \App\Station::findOrFail($station_id);
    
        $cast_id = \App\Newscast::where([
            ['for_station_id', $station->id],
            ['name_input', $name_input]
        ])->get();
        $cast = \App\Newscast::findOrFail($cast_id);
    
        $relations = [
            'anchors' => \App\User::get()->pluck('name', 'id'),
            'casts' => \App\Newscast::where('cast_id', $cast->id),
            'assignments' => \App\Assignment::where('cast_id', $cast->id)->get(),
        ];
        return view('assign.list', compact('castName') + $relations);
    }
    

    web route

    Route::get('assign/{calls}-{name_input}', 'AssignmentsController@showAssignmentsByCastName')->name('assign.list');