How to add many to many extra pivot columns? - laravel

I have two tables products and orders which are linked by a pivot table order_product with the id of each table. But I also want to add an amout column to the pivot table. How can I do this with laravel Voyager?

Easily just define it in your migration file of order_product and access it from relation function as bellow:
Schema::create('order_product', function (Blueprint $table) {
$table->unsignedBigInteger('order_id');
$table->unsignedBigInteger('product_id');
$table->unsignedInteger('amount');
});
and for example in your product model:
public function orders()
{
return $this->belongsToMany(Order::class)
->withPivot('amount');
}

Related

Relationship not working and looking for a strange table name?

I have created a migration for a lookup table with a many to many relationship.
Schema::create('user_partner__organization', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('partner_organization_id');
$table->foreign('user_id')
->references('id')
->on('users');
$table->foreign('partner_organization_id')
->references('id')
->on('partner_organizations');
});
}
Then I am setting up the relationships to be able to go through the user_partner__organization table
In UserPartnerOrganization model
public function partnerOrganizations()
{
return $this->hasMany(PartnerOrganization::class);
}
And in PartnerOrganization
public function userPartnerOrganizations()
{
return $this->belongsToMany(UserPartnerOrganization::class);
}
And finally I am trying to go through the relationship to get a user_id when I know the partner_organization_id which I have in the $organization
$test = $organization
->partnerOrganization()
->first()
->userPartnerOrganizations()
->first();
The partnerOrganization relationship is working nicely but when I try to implement the userPartnerOrganizations I get this error in my log file
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'homestead.partner_organization_user_partner_organization' doesn't exist in /home/vagrant/api/vendor/laravel/framework/src/Illuminate/Database/Connection.php:359
Don't understand where this strange table name is coming from or why the relationship is not working.
since your not following Laravel convention in tables name, you have to provide the pivot table name in relation declaration:
public function partnerOrganizations()
{
return $this->belongsToMany(PartnerOrganization::class,'user_partner__organization','user_id','partner_organization_id');
}
public function userPartnerOrganizations()
{
return $this->belongsToMany(UserPartnerOrganization::class,'user_partner__organization','partner_organization_id','user_id');
}
also note that the relation from both side should be belongsToMany
more about many to many relation in Laravel doc.

laravel hasMany polymorphic relationship in where clause

I am trying to select the picture with the most likes within a specific category from my database. I have a database table storing the pictures and a table storing the likes. The pictures table is related to likeable table through a hasMany polymorphic relationship.
Like model:
public function likeable()
{
return $this->morphTo();
}
Picture model:
public function likes()
{
return $this->morphMany('App\Like', 'likeable');
}
Home Controller:
Picture::where('picture_type', 'food')->orderBy(likes(), 'desc')->first();
Likeable Migration:
public function up()
{
Schema::create('likeable', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->integer('likeable_id');
$table->string('likeable_type');
$table->timestamps();
});
}
So far, the above line of code, in my home controller returns an error. From what I understand, the likes method has to be called on a specific instance. However, I do not know how to implement this all the while keeping my where clause.
Thank you for your help.
I assume you are wanting to order pictures by the most likes.
In which case, you want something like this:
Picture::withCount('likes')->where('picture_type', 'food')->orderBy('likes_count', 'desc')->first();

get extra column with eloquent hasManyThrough

i have three tables cart , cart_products , products
i have that relation in cart table
public function products()
{
return $this->hasManyThrough(Product::class,CartProducts::class,'cart_id','id' )->withPivot('cart_products');
}
and this is my cart_products table
Schema::create('cart_products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedInteger('product_id')
->references('id')->on('products')->onDelete('cascade');
$table->unsignedInteger('cart_id')
->references('id')->on('carts')->onDelete('cascade');
$table->unsignedInteger('quantity');
$table->timestamps();
});
i got all products finally , but i need to get quantity column with that realtion
any help?
Use the many to many relation with belongsToMany()
public function products()
{
return $this->belongsToMany(Product::class)->withPivot('quantity')->withTimestamps();
}
You may retrieve the qauantity column from the cart_products pivot table by passing the column name to the withPivot method
//...
return $this->belongsToMany('App\Product')
->using('App\CartProducts')
->withPivot('quantity');
See
Defining Custom Intermediate Table Models
in Docs

How to use relationship in laravel?

I use work with relationship in laravel 5.6.
I create product table with migration:
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('slug');
$table->text('description');
$table->string('tags');
$table->string('original_price');
$table->integer('view_order')->default(0);
$table->unsignedInteger('admin_id');
$table->foreign('admin_id')->references('id')->on('admins');
$table->boolean('status');
$table->timestamps();
});
And i create category table with migration:
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->boolean('status');
$table->timestamps();
});
And create product_categories table with migration:
Schema::create('product_categories', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('product_id');
$table->foreign('product_id')->references('id')->on('products');
$table->unsignedInteger('category_id');
$table->foreign('category_id')->references('id')->on('categories');
$table->timestamps();
});
Now, I use Bootstrap Multiselect for categories in one product.
In category model:
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function products()
{
return $this->belongsToMany(Product::class);
}
In Product model:
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function categories()
{
return $this->belongsToMany(Category::class);
}
How to add category_id and product_id in product_categories table with relationship?
Check the documantation related to Many to many Relationships.
Your pivot table doesn't follow Laravel's convention, either update your table name or update your relationships to address this issue.
The convention is the alphabetical order of the two models, thus your pivot table should be named: category_product
If you do not want to update the table name, update your relationships.
public function categories()
{
return $this->belongsToMany(Product::class, 'product_categories')
}
public function products()
{
return $this->belongsToMany(Category::class, 'product_categories')
}
Now to "save an entry to the pivot table" -or in other words: to create the relationship between the two models- you may use attach or sync method.
$product->categories()->attach($category);
$product->categories()->attach([$categoryId1, $categoryId2]);
sync is different.
The sync method accepts an array of IDs to place on the intermediate table. Any IDs that are not in the given array will be removed from the intermediate table.
To detach (delete entry in pivot table), simple use the detach method.
$product->categories()->detach([1, 2]);
Of course, do the same for Category.
Your model names are Product and Category and the derived relational table will be category_product because category came before product in alphabetical order.
You only have to add the pivot table:
public function categories()
{
return $this->belongsToMany(Product::class, 'product_categories')
}
public function products()
{
return $this->belongsToMany(Category::class, 'product_categories')
}
Now for save with relationship:
$product->categories()->attach($category);
$product->categories()->attach([$category_id_1, $category_id_2]);
You only have to add the pivot table:
public function products()
{
return $this->belongsToMany(Product::class, 'product_categories');
}
public function categories()
{
return $this->belongsToMany(Category::class, 'product_categories');
}
By default, laravel derives the table name from the alphabetical order of the related model names. Here your model names are Product and Category and the derived relational table will be category_product because category came before product in alphabetical order. Either you can change the table name or you can override this my mentioning the table name as the second parameter in the relational method as follows.
public function products()
{
return $this->belongsToMany(Product::class, 'product_categories');
}
public function categories()
{
return $this->belongsToMany(Category::class, 'product_categories');
}

Laravel Eloquent Relationship Many to Many Naming Convention

I am creating a purchased table in my application. So I have 2 tables : User and Product. Its a many to many relationship.
I know we have to create a new table for this. The naming convention for table is plural as users and products.
How would we call this purchase table? user_product or users_products?
Also I think I would need a model for this correct? If I do need a model should the naming convention for this model be User_Product?
From the documentation:
As mentioned previously, to determine the table name of the relationship's joining table, Eloquent will join the two related model names in alphabetical order. However, you are free to override this convention. You may do so by passing a second argument to the belongsToMany method
In your case, Laravel assumes that your joining table would be named product_user. No extra model is needed:
User.php
class User extends Model
{
//...
public function products()
{
return $this->belongsToMany(Product::class);
}
//...
}
Product.php
class Product extends Model
{
//...
public function users()
{
return $this->belongsToMany(User::class);
}
//...
}
And your schemas would look like so:
users table migration
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
//...
});
products table migration
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
//...
});
product_user table migration
Schema::create('product_user', function (Blueprint $table) {
$table->integer('product_id');
$table->integer('user_id');
//...
});
About the naming Convention, thats just something that will make your code more readable i think, so you can name it as you like(in case you are new and learning , my opinion is that its better to avoid being stuck in conventions at first , im still learning my self)
anyway a pivot model is not required, unless you simply need some custom behaviour
I think this would help you
class User extends Model
{
/**
* The products that belong to the shop.
*/
public function products()
{
return $this->belongsToMany('App\Products');
}
}
you can do this : $user->products or to query $product->users, or both.
Now, with such declaration of relationships Laravel “assumes” that pivot table name obeys the rules and is user_product. But, if it’s actually different (for example, it’s plural), you can provide it as a second parameter:
return $this->belongsToMany('App\Products', 'products_users');
If you want to know how to manage these you can find more in here

Resources