Nested eloquent relationship - laravel

I just started my first laravel project today and stumbled upon this confusing situation,
I intended to use eloquent relationship instead of manually joining tables on query. So here it goes...
I have 3 tables which are users , tbl_instruments_taught , tbl_instruments
users table does not hold any of the table's ID,
tbl_instruments_taught - holds the id of user and intruments
Note: user can teach multiple instruments
Now, I implemented a hasOne on my other result set but I dont think hasOne works on this one. I read about belongsToMany but as I try implement it, it seems like every minute, it gets confusing.
Any idea?

I think you are looking for pivot table and relation many to many.
You have users table, instruments table (user has many instruments and one instrument could belong to many users) and user_instruments pivot table. Here db model:
And then add belongsToMany relationship in User and Instrument model (with specified pivot table). Like so:
//IN USER MODEL
public function instruments()
{
return $this->belongsToMany('App\Models\Instruments', 'users_instruments', 'user_id', 'instrument_id');
}
//IN INSTRUMENT MODEL
public function users()
{
return $this->belongsToMany('App\Models\Users', 'users_instruments', 'insrument_id', 'user_id');
}
Now you can reach instruments/users data through laravel relations/eager loading.

Related

how to retrieve users based on the selected categories and sub categories from database in laravel

I would like to begin with the messy things I have done with the database architecture.
I have put the fields title, description, donation_amount, in the users table which should have been in a different table. But now if I change this, I would have to change a lot of things.
The ManyToMany relation is already setup between these tables in laravel. I tried to join tables that query builder as well.
There are different roles in the application. We will talk specifically about Donor When a Donor registers in the Application. It selects multiple categories and sub_categories which stores in selections table.
Now when a donor logs in to the application. It should only get the records based on the categories selected.
Now I am confused how can I retrieve the users based on the logged in users selected categories and sub_categories.
I have tried joining the tables which works well but it is getting all the results against the joined tables.
DB::table("users")->select('users.*')->from('categories')
->join('selections','categories.id', '=', 'selections.category_id')
->join('users', 'users.id','=', 'selections.user_id')
->join('sub_categories','sub_categories.id', '=', 'selections.sub_category_id')
->where('users.status','approved')->paginate(6);
Relations in the model Category
public function users() {
return $this->belongsToMany(User::class,'selections');
}
Relations in the model User
public function categories() {
return $this->belongsToMany(Category::class,'selections');
}
If there is a way of doing this calling eloquent relationships. I would love the help else It would be evenly nicer to get the job done with the joins I have already implemented.
Use has-many-through relationship.
https://laravel.com/docs/9.x/eloquent-relationships#has-many-through
In other way you can query like this :
DB::table("users")->select('users.*')
->whereIn('users.id',function($query) use ($specific_category_id){
$query->select(''user_id')->from('selections')->where('category_id',$specific_category_id)
})
->where('users.status','approved')->paginate(6);

Laravel - Eloquent relation - many-to-many - get intermediate table columns

I have a question about Laravel Eloquent Relations.
I have the following table situation:
Table guests:
id
name
...
Table landing_pages:
id
name
...
A guest can have several landing pages. And a landing page will have multiple guests.
So I thought, I can use a many-to-many relationship there and I created a new table
Table guests_landing_pages:
id
guest_id
landing_page_id
...
I would be able to use this the following way:
In guest Model I can do this, to create the many-to-many relationship:
public function landing_pages()
{
return $this->belongsToMany(\App\Models\LandingPage\LandingPage::class, 'guests_landing_pages','landing_page_id','guest_id');
}
... and the other way round in landing_page model.
But actually the table guests_landing_pages contains more data than just the guest_id and landing_page_id relation.
There are several other fields in it:
Table guests_landing_pages:
id
guest_id
landing_page_id
identifier_token
max_persons
answer
...
My question is now, how can I realize this best. If I would use the many-to-many relation as described above, I will not be able to access the fields in the intermediate table, won't I?
Or will the best solution to this to create a GuestLandingPages model with all the fields and create hasMany relations to/in both?
Laravel Eloquent has features for retrieving intermediate columns.
public function landing_pages()
{
return $this->belongsToMany(\App\Models\LandingPage\LandingPage::class, 'guests_landing_pages','landing_page_id','guest_id')
->withPivot('max_persons', 'answers');
}

How to make left join in many to many relationship laravel

I am new in laravel. I have 3 tables
users
ingredients
user_ingredients(pivot table)
Now i have established many-to-many relationship but I have a special requirement that I want to get matching records(which is done) with all the ingredients in ingredients table. I can do it using query_builder or raw but I want to do it in eloquent.
I have searched about 4 hours to find any solution in eloquent but did not found.
Here is my code
User Model
public function ingredients()
{
return $this->belongsToMany('App\Ingredient', 'user_ingredients');
}
Ingredient Model
public function user()
{
return $this->belongsToMany('App\User', 'user_ingredients');
}
Controller Code
$ingredients = $user->ingredients()->get();
Query Builder query
select ingredients.*,user_ingredients.liked from ingredients LEFT JOIN user_ingredients on ingredients.id = user_ingredients.ingredient_id and user_ingredients.user_id=129
I have checked has(),with() but nothing according to my requirement.
Please help me. Thanks
If I understand your question correctly, you are just trying to access all the ingredients on the user model? In that case, you should be able to just do $user->ingredients
You can access the relationship as a property on the user object. It's some behind the scenes Laravel magic that handles this.

Laravel / Eloquent - custom relation method

I have a class Report which has a belongsToMany relation to Metric. Report also additionally has a belongsTo relation to Metric.
Normally, the model returned by the belongsTo relation is the same as one of the models in the belongsToMany relation. When this is true I'd like it to be the case that each of the two relations actually looks at the same object instance (this also saves an extra trip to the db).
So, in basic terms - is there a way to get one relation to check another first, to see if a model has already been loaded, and if so, point to that object rather than creating a new one.
I tried putting some code in the belongsTo relation method for Metric but I can't get round the fact it needs to return an instance of belongsTo, which needs various things passed as constructor arguments (ie. a query object), which aren't relevant in that case that the model has already been loaded in the belongsToMany relation.
I thought of ditching the belongsTo relation and adding data horizontally in the pivot table for the belongsToMany relation, but it isn't a many-to-many relation required so that seems a bit wrong.
Thanks!
Geoff
The idea here is to write a function which would check if a relationship is loaded and return that relationship, otherwise it will return the belongsToMany. This would go in your Report class. This is also for Laravel 5. If you have 4, just remove the namespaces from the model names.
public function metric()
{
return $this->belongsTo('App\Metric');
}
public function metrics()
{
return $this->belongsToMany('App\Metric');
}
public function getMetric()
{
if(array_key_exists('metric', $this->getRelations())) {
return $this->metric;
}
return $this->metrics()->first();
}
If you do decide to just go with a belongsToMany only, I'd suggest putting a unique key on your pivot table for both ID's to keep from getting any duplicates in the pivot table.

User Relationships, Many to Many

I need to create relationships between users. As you might expect, they exist in the users table. My approach is a relationships table linking user_a_id to user_b_id.
Then, in the User model, I added:
public function relationships()
{
return $this->belongsToMany('User', 'relationships', 'user_a_id', 'user_id');
}
Unfortunately, I get an error when trying to find the relationships;
dd($user->relationships);
Output: Whoops, looks like something went wrong.
I would consider something like a "user" model, and a "group" model. The users table can have a many-to-many relationship with the groups table, and this could be defined with a "user_group" table, containing a column "user_id" and another "group_id". Then you can have a function in your User model called groups, which does return $this->belongsToMany('Group');, and a function in your Group model called Users, which goes return $this->belongsToMany('User');
Refer to this section of the Eloquent docs for further direction.

Resources