A controller that lists a team's invoices often writes where('team_id', $team->id). The page works until someone renames the column, or a second relationship also points at teams, and the query keeps using the old name. The bug looks like an empty list.
whereBelongsTo() constrains the query to the rows that belong to a model you already have. The controller stops naming team_id. Eloquent reads the foreign key from the relationship.
01 What it does
Pass the parent. For an Invoice that belongsTo a Team, the call below is a where on that foreign key, ordered newest first.
// app/Http/Controllers/InvoiceController.php
use App\Models\Invoice;
use App\Models\Team;
$invoices = Invoice::query()
->whereBelongsTo($team)
->latest()
->get();A report that covers several teams passes a collection. The query becomes a whereIn on the same key, still without the controller naming the column.
$invoices = Invoice::query()
->whereBelongsTo($teams)
->whereBelongsTo($author, 'author')
->latest()
->get();The second argument is the relationship method name when it is not the default guess from the class. author() needs 'author'. team() does not, because the model is Team.
02 Gotchas
- The parent has to be saved. A new
Teamwith no id produces a query that matches nothing, not an error. - This is the child looking up its parent. Lines that belong to an invoice you are holding are
$invoice->lines(), notwhereBelongsTo. whereHas()is the other direction: invoices that have a line matching a rule, when you do not already hold those lines.- A global scope on
Invoicestill applies.whereBelongsTo()does not turn it off.
03 Related
Belongs-to and whereBelongsTo walks the same call in the series. One to many, without the surprises is the direction that creates the rows.