Laravel 5 Inverse of belongsToMany - php

actually not sure if I am doing it correctly or there are other ways. What I have in my database are the following
brands
id: integer
name: string
slug: string
description: string
timestamp
products
id: integer
name: string
price: decimal
slug: string
description: string
timestamp
brand_product
id: integer
brand_id: unsignedInteger
product_id: unsignedInteger
Basically, brands have many products, so on my Brand model
...
public function products()
{
return $this->belongsToMany(Product::class);
}
...
However, a Product has one (1) Brand model. Pretty sure I can achieve what I want by adding brand_id on my products table and do the relationship thing on my Product model. However, I have an above database structure. What I did, on my Product model:
...
protected $appends = ['brand'];
public function brand()
{
return $this->belongsToMany(Brand::class);
}
public function getBrandAttribute()
{
return $this->brand()->first();
}
...

Your assumption of adding a brand_id on products is correct. What you are describing is a one-to-many relationship, but a database structure representing a many-to-many. Remove the pivot table and add the brand id to the products table and you'll be good to go.
// Product model
public function brand()
{
return $this->belongsTo(Brand::class);
}
// Brand model
public function products()
{
return $this->hasMany(Product::class);
}
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many

The best approach would be to remove the pivot table and define a one-to-many relation.
However, if you have to keep the schema with the pivot table, you just simply put the belongsToMany() on both of your models. There is no specific inverse of belongsToMany() in Laravel.
https://laravel.com/docs/5.5/eloquent-relationships#many-to-many

Add the following code inside your Product model:
public function brands()
{
return $this->belongsToMany('App\Brand', 'brand_product');
}
Now you can get the first row of the brands of the product by using the following code in your controller:
$product->brands()->get()->first(); // Will return the first row

Related

How can i make a relationship between my three Models where Distributor and Product model are directly connected with the Distributorproduct Model

Distributor Table - id
Product Table - id
Distributorprocuct Table - distributor_id, product_id
Distributor Model -
public function product() { return $this->hasMany(Distributorproduct::class); }
Product Model -
public function distributor() { return $this->hasMany(Distributorproduct::class); }
Distributorproduct Model -
public function distributor() { return $this->belongsTo(Distributor::class); }
public function product() { return $this->belongsTo(Product::class); }
If I write $product->distributor then it gives me all the details of distributorproduct but i need the details of distributor not distributorproduct .
If i write $distributor->product then it gives me all the details of distributorproduct but i need the details of product not distributorproduct .
Thanks in advance...
It is not clear to me what is the relationship between Product, DistributorProduct and Distributor, but I think what you want is to specify a different kind of relationship between Distributor and Product (and Product -> Distributor).
In your Distributor modal class you can try defining your product method like this:
public function product() {
return $this->hasOneThrough(Product::class, Distributorproduct::class);
}
and the distributor method in the Product modal class like this:
public function distributor() {
return $this->hasOneThrough(Distributor::class, Distributorproduct::class);
}
But your mileage may vary, this kind of relationship is ok only if a Product has a single distributor (likely), and a distributor has a single Product (unlikely I guess).
The Laravel docs have a pretty good documentation about relationships. Looks especially at the Has One Through and the Has Many Through paragraphs.

pivot table relationship Laravel

I have the following relation:
RAB hasMany products.
products belongsToMany RAB
but this products also hasMany currency that belongsToOne RAB itself.
it looks like this.
in RAB model:
public function products()
{
return $this->belongsToMany('App\ModelKeuangan\ProductsModel', 'rab_products', 'rab_id', 'products_id');
}
in products model:
public function rab()
{
return $this->belongsToMany('App\ModelUnitKerja\Perencanaan\RabModel', 'rab_products', 'products_id', 'rab_id');
}
rab_products is my intermediate/join table.
it works just fine when im syncing products data for RAB. but i cant get how to make eloquent model for syncing Currency data to rab and products.
do i need to make model for currency too? if yes, how do i define it?
my plan is make a pivot like this, but can i make relation inside pivot table?
class RabProducts extends Pivot {
//relation function to currency
}
and change my products model something like:
public function rab(){
return $this->belongsToMany('App\ModelUnitKerja\Perencanaan\RabModel')->using('App\RabProducts');
}
Create the currency model and add foreign_key product_id:
php artisan make:model Currency
Build the one-to-many between Product and Currency
and you need to add product_id in your currencies table.
In your Currency Model:
public function product() {
return $this->belongsTo('App\Product', 'product_id');
}
In your Product Model:
public function currencies()
{
return $this->hasMany(\App\Currency::class, 'product_id', 'id');
}
So that you can call it like this:
RAB::with(['products' => function($query) {
$query->with('currencies');
}])->get();
Unfortunately, the foreign_key between products and rabs is in pivot table, you cannot create the hasmanythrough with currency directly.
You can call the currency by products. Or you can create a pivot model, and then use hasmanythrough.

Set up many to many relationship in laravel eloquent

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.

Laravel - Query builder get relation

In my project I have a Polymorphic relation. This relation is as followes:
Plugins
id - integer
composer_package - string
Themes
id - integer
composer_package - string
Products
id - integer
name - text
...
commentable_id - integer
commentable_type - string
When I need to display all the products that are a Theme I do the following:
$themes = DB::table('products')->orderBy('id', 'asc')->where('productable_type', Theme::class)->get();
The code above provides me with a list of all the products where the productable_type field is filled with App/Theme, I display them with a foreach loop like this #foreach($themes as $theme). Now my problem is.
I need to get the composer_package from the themes table that belongs to that product. So say for instance. I get a product from the products table where the productable_id is 3. I want the value of the composer_package field in the themes table where the ID is 3. When I do {{ $theme->products->composer_package }} or {{ $theme->composer_package }} It gives me the error Undefined property What is causing this?
This is my product model
public function product()
{
return $this->morphTo();
}
public function order_items()
{
return $this->hasMany(Orderitems::class);
}
And this is my theme model
public function webshops()
{
return $this->hasMany(Webshop::class);
}
public function products()
{
return $this->morphMany(Product::class, 'productable');
}
Thanks in advance!
Is there any reason you are using the DB facade to pull data instead of the actual models?
One issue your are having is that your polymorphic relationship is stored in the commentable_id / commentable_type field, while your function name is product. Laravel does some of its magic just by naming alone, so let's make sure the column names and polymorphic function names match up in the product model:
public function commentable()
{
return $this->morphTo();
}
After that, try something like this in the controller:
$themeProducts = Product::where('commentable_type', Theme::class)->get();
And this in the view
#foreach ($themeProducts as $themeProduct)
{{ $themeProduct->commentable->composer_package }}
#endforeach
Your table has "commentable", but your model is looking for "productable". You're also missing a method.
in your product model add:
public function commentable(){
return $this->morphTo();
}
in your theme model modify the products() method to:
public function products(){
return $this->morphMany(Product::class, 'commentable');
}
You could also update your commentable_type and commentable_id columns in your table to productable_type and productable_id, in which case you need to rename commentable() in the code for the product model above to productable(), and 'commentable' to 'productable' in the code for the theme model above.
(Source: https://laravel.com/docs/5.6/eloquent-relationships#polymorphic-relations)
Create relations with the model as mentioned in above answers, then you can retrieve relations using with helper.
E.g.:
Product::where('commentable_type', Theme::class)->with('commentable')->get();
and then can directly use as mentioned above.
e.g.: $themeProduct->commentable

Laravel 4 Eloquent/Model Relationships

I am setting up several Models an want to know the correct approach to table structure and Model relationships.
Let's assume we have a shop containing products, each with properties size and color.
Table products
id
size_id
color_id
price
Table sizes
id
name
Table colors
id
name
Models
class Product extends Eloquent {
public function size() {
return $this->hasOne('Size', 'id');
}
public function color() {
return $this->hasOne('Color', 'id');
}
}
class Size extends Eloquent {
public function products() {
return $this->belongsTo('Product', 'size_id');
}
}
class Color extends Eloquent {
public function products() {
return $this->belongsTo('Product', 'color_id');
}
}
This way I can easily echo the color/size of a product using {{ Product->size['name'] }}. Also, I want to pass Eloquent the size's foreign key size.id like Product::where('size_id', '5') rather than its name size.name.
Problem: Doing $products = Product::has('size', '=', '5')->get() does not give me any results, yet doing $products = Product::where('size_id', '5')->get() does.
I am pretty confused, what went wrong?
I think that the problem is that your ::has() method is looking for products with exactly 5 different sizes on each specific product, which would assume that you would be using $this->hasMany('Size') in your Product model. Where as the ::where() method is returning results where the size of the product is 5.
In the documentation they use an example of comments. A post will have a list of comments. You can find posts that have at least one comment (ie. Post::has('comments')->get()) or you can find posts that have more than 3 comments (ie. Post::has('comments', '>=', '3')->get()).
http://laravel.com/docs/eloquent#querying-relations

Categories