Laravel Nova: Limiting BelongsToMany options
More things you can do when extending Laravel Nova resources
For a project I'm working on I want to assign multiple Room
s to Reservation
s. This is easy using a BelongsToMany field in Laravel Nova.
app/Nova/Reservation.php
namespace App\Nova;
use Laravel\Nova\Fields\BelongsToMany;
class Reservation extends Resource
{
public function fields(Request $request)
{
return [
BelongsToMany::make('Rooms')
];
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
But what if you only want to display rooms that are not occupied?
If you have read my other post about Showing more details in a BelongsTo field, you might know where I'm going with this.
Room
Nova resource
Step 1: Extend your And write a custom relatableQuery
app/Nova/Helpers/AvailableRoom.php
namespace App\Nova\Helpers;
use App\Nova\Room;
use App\Reservation;
use Laravel\Nova\Http\Requests\NovaRequest;
class AvailableRoom extends Room
{
public static $globallySearchable = false;
public static $displayInNavigation = false;
public static function uriKey() :string
{
return Room::uriKey();
}
public static function relatableQuery(NovaRequest $request, $query)
{
// the reservation we're trying to attach a room to...
$reservation = $request->findModelOrFail();
// use some code to find and fill $occupied_room_ids based on $reservation
$occupied_room_ids = []; // write your own logic...
// return all rooms that are not occupied
return $query->whereNotIn('id', $occupied_room_ids);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Step 2: Use this extended resource in your BelongsToMany field
app/Nova/Reservation.php
namespace App\Nova;
use Laravel\Nova\Fields\BelongsToMany;
use App\Nova\Helpers\AvailableRoom;
class Reservation extends Resource
{
public function fields(Request $request)
{
return [
BelongsToMany::make('Rooms', 'rooms', AvailableRoom::class)
->help('Only available rooms are shown.'),
];
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
That's really all there is to it! 🎉