Querying related items in multiple relationship
Created 5 years ago by emergingdzns

I’ve got a stream called Threads. Inside of Threads I have a multiple relationship called participants that is related to the UserModel. In my controller, I’m trying to make a simple call to get all of the threads a user is added to as a participant.

I’m tying my brain up in knots because it’s sort of backwards from the normal approach. I could add a field to the users table in the admin panel that is a multiple relationship to the threads table and then query from there but I don’t feel that’s the appropriate way to do it because it removes the pivot table from the picture and then I have the same problem in reverse if I need to get all users for a given thread.

I was thinking maybe I need to bind to the user model in the module service provider but the problem is that the threads_participants table has no actual model so I’m getting confused as to how to bind in a way that lets me do something like this: $threads = $user->threads;

It’s probably something simple that I’m not seeing but I’m getting stuck on this.

I appreciate any help you can offer.

ryanthompson  —  5 years ago

In order to query based on a multiple you would need to do some joining just like native Laravel would require (it's a BelongsToMany relation).

However based on your code here and your Slack message I would look into using hooks in order to add the functionality to the users module that you want.

https://github.com/anomalylabs/reactions-extension/blob/master/src/ReactionsExtensionServiceProvider.php#L54-L78

emergingdzns  —  5 years ago

Ugh. I'm just not getting it. It seems like I need a model for the default_messages_threads_participants pivot table that pyro makes in order to make any of these queries work. I think I have just enough of a headache that it's keeping me from seeing the obvious... This module is similar to the forum in that there's a "discussion" stream (I call threads). Then there's a "messages" stream where each thread can have multiple messages, all chronological etc, just like in email essentially. But, in this module, each thread can have multiple participants in the thread and each participant can see all messages in that thread. A participant is a user in the system.

My stumbling block is that when a user logs into the site on the front end, I need to be able to query the list of threads where the user is a participant. Then, I can loop through the threads for recent messages to display. Again, sort of a cross between a forum and email.

So my streams/fields are: Messages - message_content (wysiwyg) (some other fields irrelevant to this issue)

Threads - subject (text) messages (multiple -> messages model) participants (multiple -> users model)

Since I can't (and really don't want to) change the Users model, I'm having trouble with the idea of figuring out how to get the threads.

I can't jsut say Auth::user()->threads as there's no threads multiple field type added to the users table. I was trying to add to the ThreadRepository and do something like this:

public function findByParticipant($id) {
    return $this->model->participants()->contains('related_id', $participant)->get();
}

I'm certain I'm missing something simple but I'm just not seeing it.

Thanks again for the guidance.

ryanthompson  —  5 years ago

Ok so this is good! The fact that there is no (nor do we want it) multiple FT on users.. we don't want to override the model cause what if something else want's to override. We almost want to add a method to it - from somewhere else right?

So you can almost copy what the comments repository does verbatim (others note 404 is because this is a private PRO repository): https://github.com/anomalylabs/comments-module/blob/1.0/src/CommentsModuleServiceProvider.php#L125

Instead of the base EloquentModel just inject the UserModel. Then basically pretend the closure is your model method like you were modifying the class itself. What you see there, those three hooks, provide this functionality (I'll use $user since it the methods are bound to ALL EloquentModels):

$user->discussions();
$user->discussion($channel = 'default');
$user->getDiscussions();

We just added the ability to use those methods and that logic without overriding or extending or otherwise changing the UserModel or any other model for that matter. That sir, is the essence of hooks!