Versatile
Versatile

Reputation: 158

Laravel Eloquent query with relation

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

Answers (1)

Versatile
Versatile

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

Related Questions