Set up many to many relationship in laravel eloquent - php

What is the best practice to setup many to many relationship with post and categories in laravel eloquent? Do I create a separate model for pivot table?
This is how I defined it in post model.
public function category()
{
return $this->belongsToMany('App\Category');
}

you need to change the relationship method name to categories()
/**
* The categories that belong to the product.
*/
public function categories()
{
return $this->belongsToMany('App\Category', 'category_product');
}
category_product - is your pivot table, you can define if you change the naming convention or its optional.
In Category model, you can define it like blow
/**
* The users that belong to the role.
*/
public function products()
{
return $this->belongsToMany('App\Product', 'category_product');
}
If you require you can create a model for pivot table, in my case this is how i store data to pivot table (using attach method)
$product->categories()->attach($category); //list of category id's
And you can update it again using detach method or synch method.
$product->categories()->sync($synch); // new category id's

The best way to do this is:
public function categories(){
return $this->belongsToMany('App\Models\Categories', 'categories_posts', 'post_id', 'category_id');
}
And then in your Categories model:
public function posts(){
return $this->belongsToMany('App\Models\Posts', 'categories_posts', 'category_id', 'post_id');
}
belongsToMany() method can receive up to 4 parameters, the first one is the location of your model to link, the second is the name of the pivot table, the third one is the current model foreign key and the fourth one is the other's model foreign key.
You can also specify extra data on pivot table using the withPivot() method like this for example:
public function categories(){
return $this->belongsToMany('App\Models\Categories', 'categories_posts', 'post_id', 'category_id')->withPivot('quantity');
}
And then for attaching you can do as follows:
$post = Posts:find(1);
$post->categories()->attach($category_id, ['quantity' => 2]);
But please, refer to Laravel's official documentation:
https://laravel.com/docs/5.6/eloquent-relationships

To define this relationship, three database tables are needed: post, category, and category_post. The category_post table is derived from the alphabetical order of the related model names, and contains the category_id and post_id columns.

Related

In Laravel Eloquent how to define relationship through secondary table? (Always returning 0 relations)

I feel like this should work. I have a list of products and categories (types).
Tables:
Products
- id
- name
- etc
Types
- id
- name
- etc
ProductTypes
- product_id
- type_id
Now, I feel like in the Type model in Laravel, I should be able to define this relationship:
public function products()
{
return $this->hasManyThrough(Product::class, ProductType::class, 'type_id', 'id');
}
I've tried other variations with the secondary ids in the additional parameters but no luck, always an empty list. Is ProductTypes a pivot table and therefore should be dealt with differently?
Edit: What's weird is that for the final 2 parameters ($localKey = null, $secondLocalKey = null) even if I enter complete garbage no error is thrown but these 2 parameters $firstKey = null, $secondKey = null have to be correct).
You are using the wrong relationship. Based on your database structure, a product can belong to many type. Therefore, it should be a BelongsToMany instead of a HasManyThrough.
You can achieve what you want with the following method, by passing the table name of your ProductTypes as the second parameter:
public function products()
{
return $this->belongsToMany(Product::class, 'product_types');
}
If your ProductType model extends Illuminate\Database\Eloquent\Relations\Pivot, you can do:
public function products()
{
return $this->belongsToMany(Product::class, 'product_types')
->using(ProductType::class);
}
For more information about Many to Many relationships: https://laravel.com/docs/6.x/eloquent-relationships#many-to-many

Laravel Many-To-Many relation returns no results

I am currently learning Laravel and I have an issue which I can't seem to find a solution for. I have a many-to-many relation between two tables that always returns nothing. Let me show you the basic setup:
My posts Model:
// App\Post.php
protected $fillable = [
'name',
'description'
'videopath'
];
public function Tags()
{
return $this->belongsToMany('App\Tag');
}
public function Cats()
{
return $this->belongsToMany('App\Cat');
}
My tags model:
// App\Tag.php
protected $fillable = [
'name',
'description'
];
public function exercises()
{
return $this->belongsToMany('App\Exercise');
}
My posts controller:
// PostController.php
public function show($id)
{
$post = Post::find($id);
return view('posts', ['post'=>$post];
}
The view:
// posts.blade.php
#foreach($post->tags() as $tag)
//do stuff
#endforeach
The intermediate table is called post_tag and contains the post_id and tag_id columns. At first it returned the results as expected but after some while all of my posts didn't return any tags anymore. The cats model looks similar to the tags model. Anyone has an idea?
Check the name of your Tags function. In your view you are calling "tags" instead of "Tags".
Have you created the intermediate table in your database? If so, check the naming convention (alphabetic order) that Laravel uses to find it: in your case it should be tag_post. if not, customize the name of the table when defining the relationship.
Many To Many
Many-to-many relations are slightly more complicated than hasOne and hasMany relationships. An example of such a
relationship is a user with many roles, where the roles are also
shared by other users. For example, many users may have the role of
"Admin". To define this relationship, three database tables are
needed: users, roles, and role_user. The role_user table is derived from the alphabetical order of the related model names, and contains the user_id and role_id columns.
Taking your view:
#foreach($post->tags() as $tag)
//do stuff
#endforeach
$post->tags() will return the relationship instead of the actual collection. You want $post->tags instead or $post->tags()->get().

Laravel 5.4 relationship

Hi I need to display users items from table name Items.
I have 3 models.
User model:
public function userItem()
{
return $this->hasMany('App\UserItem', 'item_id');
}
UserItem model:
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
What to write to Item Model to make this relationship successful. So I could display items from items table.
If I now do this:
I get info from user_items table from DB.
when I do this #foreach(Auth::user()->userItem as $item) I get this:
Column not found: 1054 Unknown column 'user_items.user_items' in
'where clause'
I think you want to use many to many relation
you have 2 models User and Item
and 3 tables : -users -items -user_items
User Model should be like this:
public function userItem()
{
return $this->belongsToMany('App\Item','user_items','user_id','item_id');
}
and Item Model:
public function user()
{
return $this->belongsToMany('App\User','user_items','item_id','user_id');
}
and you need a table that you named it user_items
and you dont need to define userItem model you can remove relations in this model
in your blade use this code:
#foreach(Auth::user()->userItem as $item)
You are exhibiting a many-to-many relatioship, and yet using methods for one-to-many relationships. For a many to many relationship, use the following code in your models:
//user model:
public function userItem()
{
return $this->hasMany('App\UserItem', 'user_items', 'user_id', 'item_id');
}
//userItem Model:
public function user()
{
return $this->hasMany('App\User', 'user_items', 'item_id', 'user_id');
}
For a many-to-many relationship, you need a hasMany method on both your models.
For information on the parameters to the hasMany method as well as other information on many-to-many relationships, please read the documentation on many-to-many relationships: https://laravel.com/docs/5.4/eloquent-relationships#many-to-many
Hope this helps.

Eloquent belongsTo relationships

Not sure why it's now working for me.
I have two tables
events
- id
selections
- id
- event_id
From my Event model I want to relationship selections
class Event extends Model
{
...
public function selections()
{
return $this->belongsTo(Selection::class, 'event_id', 'id');
}
}
My problem is that $event->selections relationship is not working. Keep getting null back.
With the database schema, it is hasMany relation instead.
public function selections()
{
return $this->hasMany(Selection::class, 'event_id', 'id');
}
See One to many relationship in documentation.

Can't get Eloquent's hasManyThrough to work for a basic example

Here are my relationships:
User
id
Collection
id
UserCollection
user_id
collection_id
How can I get something like $user->collections to return all Collection objects that belongs to the user? A UserCollection simply links a User to a Collection. This allows a user to have multiple collections, but also allows a collection to belong to multiple users.
What I'm currently trying is to specify that UserCollection belongs to a User on user_id, and belongs to a Collection on collection_id.
// UserCollection
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function collection()
{
return $this->belongsTo(Collection::class, 'collection_id');
}
Then specifying that a User has many Collections through UserCollection.
// User
public function collections()
{
return $this->hasManyThrough(Collection::class, UserCollection::class);
}
I've also tried explicitly setting the column names of the hasManyThrough relationship, but the join tries to use an id column on the UserCollection model, which does not exist as there is no primary key:
public function collections()
{
return $this->hasManyThrough(Collection::class, UserCollection::class, 'user_id', 'collection_id');
}
You're overcomplicating things here. You don't need hasManyThrough. What you need is belongsToMany() for a many-to-many relationship.
First, get rid of your UserCollection model. You don't need it.
Then change your relations to this:
public function collections(){
return $this->belongsToMany('Collection', 'user_collections');
}
public function users(){
return $this->belongsToMany('User', 'user_collections');
}
For more information take a look at the official docs on relations

Categories