Reputation: 158
In a Laravel environment (v 5.7) I've two tables: films and versions related in a 1 to Many relationship defined in Models as so:
class Film extends Model {
...
public function versions() {
return $this->hasMany(Version::class);
}
}
class Version extends Model {
...
public function film() {
return $this->belongsTo(Film::class);
}
}
I want to pick a random Version of a Film and its related parent Film, so in a controller I do this:
...
use App\Film;
use App\Version;
class HomeController extends Controller {
...
public function index() {
$rndVersion = Version::inRandomOrder()->first();
$relatedFilm = $rndVersion->film->first();
All works fine, except the fact that the returned film is always the first of the entire recordset, and not the parent of the version I previously loaded from the DB.
I've tried to retrieve all together with:
$rndVersion = Version::inRandomOrder()->with('film')->first();
and it works, but it packs all in a single object stored in $rndVersion, and I'd rather prefer to keep the two things separate.
So, what am I doing wrong? What shall I generally do to get the parent record of a selected/loaded one?
Thank you in advance.
Upvotes: 0
Views: 1449
Reputation: 158
I found the issue...
The way you call the relationship method defined in the Model changes the returned result.
In general, if you call:
$model->relationship() //with parenthesis
an instance of the relationship is returned. You are calling the method as a method and, as it is for Eloquent model classes, it "serves as powerful query builder" and "provides powerful method chaining and querying capabilities" (see here).
Otherwise if you call:
$model->relationship //without parenthesis
you get directly an instance of the Collection. This way you are calling the method as a property and getting a Laravel Collection thus letting you loop on the collection, get record (model) properties and use all the methods of the Collection class.
So, in my case, writing
$rndVersione = Version::inRandomOrder()->first();
$rndFilm = $rndVersione->film()->first(); //film() WITH parenthesis
works, I guess because the first() method is called on the relationship as a method, therefore maintaining the correctness of query building.
Upvotes: 1