简体   繁体   中英

Correct way to query on one-to-one relationship? (Laravel 7)

Let's say I have two models in a one-to-one relationship: Person and PhoneNumber.

On the Person model, I define:

public function phone() {
    return $this->hasOne('App\PhoneNumber');
}

And on the phone number, I define:

public function person() {
    return $this->belongsTo('App\Person');
}

So that is how the one-to-one relationship is defined in the code.

Let's say the Person model contains columns with info about the person, for example, age. Meanwhile, the PhoneNumber may contain information such as whether or not it is a cell phone or landline.

What is the correct way, using Laravel best practices, to write a query that selects all people over the age of 65 who have a cell phone?

I know I could do something like this:

$results = Person::where('age', '>', 65)
             ->whereHas('phone_number', function($q) {
                 $q->where('type', 'cell');
             })->get(); 

However, this is just a plain query and doesn't take advantage of the hasOne/belongsTo relationship. My question is, is there a more idiomatic, simpler way to write the same query in Laravel?

The code you provided is already making use of the relationship as you do not have to manually join the tables together nor specify what the foreign keys are, although I'm not sure why you wrote the relationship on the whereHas method as phone_number instead of phone as per the relationship definition code above. It should be:

$results = Person::where('age', '>', 65)
             ->whereHas('phone', function($q) {
                 $q->where('type', 'cell');
             })->get(); 

I do believe that in general, any kind of filtering that can be done in the database should be done in the database, otherwise if you want it to be done on the php side you can do it like this:

$results = Person::with('phone')->get()
             ->filter(function($p){
                 return $p->age > 65 && ($p->phone->type ?? '') === 'cell';
             });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM