Querying the multiple fields in controller
Created 7 years ago by emergingdznsI'm probably just missing something but I'm having trouble figuring out how to query the multiple relationship fields I have in my module. Here's hypothetical example. I have a stream called "kids". In the stream I have a multiple relationship field type called "contacts". Each kid in the kids stream can have multiple contacts. So far, so good. Now, for the sake of the example I have a "contacts" stream. Each stream has a single relationship to the users module. The reason being is that the user can log in to manage their contact information.
What I need to be able to do is have the contact open a page that runs a method in the controller, we'll call it "myKids". In that controller method, I fetch the contact record for the authenticated user. Then I do something like this in the controller:
public function myKids(KidRepositoryInterface $kids, ContactRepositoryInterface $contacts)
{
$user = Auth::user();
$contact = $contacts->findByUserId($user->id); // this is working and giving me back a contact object from the repository.
$my_children = $kids->findByContactId($contact->id);
dd($my_children):
}
I'm having trouble connecting the dots in the KidRepositoryInterface (really the KidRepository.php file) in figuring out how to write the query that will give me all kids that have the authenticated user in their record. Here's my KidRepository function:
public function findByContactId($contactId)
{
return $this->model->where('contacts',$contactId)->get();
}
Obviously this isn't working but for some reason I'm brain-farting on the solution. In raw laravel I'd just create a model for that kids_contacts table and it'd be an easy query. But it's different with Pyro so I'm just not grasping it. Any help would be appreciated.
I think I may have just answered my own question...
return $this->model->contacts()->where('related_id',$contactId)->get();
Sometimes it helps to just write it out...
Nevermind. That solution just gives me a Contacts Collection. I need the Kids collection where the contact is the $contactId. Any thoughts?
Figured out the better solution. I used the main KidModel and added some static functions there. Duh.
For each relationship you can have reverse relationships defined accordingly that will give you that $contact->kids
flow (if the natural relationship is $kid->contactfor example). Just a matter of looking that up and querying. I would try not to do
findByFooId($id)methods if you can help it and define the relationship and a getter for the relationship (like
foo()and
getFoo()` for example). When at all possible having the relationship clearly defined is best. Rather than relying on whereId stuff.
Hope this helps! Glad you worked it out 😊
Thanks Ryan. I created a getMyKids function like this using old Laravel methods:
public static function getMyKids($id) {
return self::with($model)->whereHas($model, function($query) use ($id) {
$query->where('entry_id', $id);
})->get();
}
I'll try your solution. I didn't realize we could do reverse relationships like that.
@ryanthompson I finally got a chance to try your solution (tried both $contact->kids and $contact->kids()). Without the quotes I get nothing at all, and with the () I'm getting an error that tells me that the reverse isn't working.
[2017-05-08 02:52:36] local.ERROR: BadMethodCallException: Call to undefined method Illuminate\Database\Query\Builder::kids() in /path/to/my/site/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:2450
In my example though I'm using a multiple relationship so the flow would be $kid->contacts (not $kid->contact) so I'm thinking maybe because it's multiple it doesn't work the same?
You have to defined the reverse relations yourself: https://laravel.com/docs/5.3/eloquent-relationships
Only the assigned relations are automatically compiled on the model. Reverse is manual. Checkout the TypeModel
in pages/posts for example. Pages have type_id
so the relation on TypeModel
must be an inverse / reverse of the former.
Ooooh ok. Sorry. I thought you were saying it was auto. I'll mess with it. Thanks.
Hmmm. The pages/posts modules have a type_id and entry_id field in the posts/pages model themselves, but that won't work for me because each kid can have multiple contacts. So there's no contact_id field.
Figured out the better solution. I used the main KidModel and added some static functions there. Duh.