pivot table relationship Laravel - php

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.

Related

how to get desired column from other table

there are two tables products and categories, that I created by PHPMyAdmin.
In the products table, it has a column name prd_category that has the foreign key of table categories named cat_id(primary key of categories table).
i am quite new in laravel
i want return all data from product table with category name(cat_name) from another table
//here is my controller
use App\Models\product;
class items extends Controller
{
public function sample(){
return product::all();
}
}
//route
Route::get('/',[items::class,'sample']);
//model for products table
class product extends Model
{
use HasFactory;
function category(){
return $this->hasOne('App\Models\category','cat_id','prd_id');
}
}
//model for category
class category extends Model
{
protected $table='categories';
use HasFactory;
}
pls help and thanks in advance..
you can use this code:
$products = product::whereHas('category',function($q)use($cat_name){
$q->where('name',$cat_name)
})->get();
or :
$categories = Category::where('name',$cat_name)->get()->pluck('id')->toArray()
$products = product::whereIn('category_id',$categories)->get();
Are you sure that one-to-many relation is correct? If a product can belong to many categories, you need to use many-to-many relations. Furthermore, if something else belongs to categories you should use many-to-many polymorphic relations. But let's go with one-to-many.
First, the relation function in Product.php looks incorrect. I think products should belong to a category.
function category(){
return $this->belongsTo('App\Models\Category','cust_name','name');
}
Then you need to define reverse relation in Category.php
function products(){
return $this->hasMany('App\Models\Product','cust_name','name');
}
When you define the relations properly, all you need yo do is to fetch data in controller:
use App\Models\Category
...
Category::with('products')->get();
you can use relationship with forign key like pro_id
function category(){
return $this->belongsTo('App\Models\Category','pro_id');
}
function products(){
return $this->hasMany('App\Models\Product','id');
}
$cat = Category::with('products')->all();
in Blade :
{{ $cat->products->cat_name; }}

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.

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 5 Inverse of belongsToMany

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

Querying with relationship not working

I am trying to grab an InvoiceDetails record and the matching Product record via the product foreign key.
This isn't working:
$r = InvoiceDetail::with('products')->find(52184)->toArray();
The 2 database calls are
SELECT * FROM `invoice_details` WHERE `id` = '52184' LIMIT 1
SELECT * FROM `products` WHERE `products`.`id` in ('0')
Where am I going wrong?
Table Structure of invoice details:
Schema::create('invoice_details', function (Blueprint $table) {
$table->increments('id');
$table->integer('invoice_id')->unsigned();
$table->integer('product_id')->unsigned();
$table->integer('quantity');
$table->foreign('product_id')->references('id')->on('products')->onDelete('restrict')->onUpdate('cascade');
$table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade')->onUpdate('cascade');
});
Table structure for Products:
Schema::create('products', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
});
Products Model:
class Product extends \Eloquent
{
public function products()
{
return $this->hasMany('InvoiceDetail');
}
}
Invoice Details Model:
class InvoiceDetail extends \Eloquent
{
public function details()
{
return $this->belongsTo('Invoice');
}
public function products()
{
return $this->belongsTo('Product');
}
}
Your relationships are weird. (Okay, that wasn't really any longer.)
Assuming that an Invoice can belong to many Products (with specific details about each such as quantity), and that a Product can belong to many Invoices, you have a classic pivot table scenario. In which case, you're doing extra work and making life more difficult for yourself than it has to be.
If that's the case, there are a few steps you can take to reduce your code and make life easier:
Remove the InvoiceDetails model. Laravel can handle pivot tables on its own pretty well. So unless you have something really custom that you need the pivot table model to handle, you don't need it.
Update your Product model. You have a products() method in the Product model. That doesn't really make any sense. Don't products belong to invoices? Let's fix that.
class Product extends Eloquent
{
public function invoices()
{
return $this->belongsToMany('Invoice', 'invoice_details', 'product_id', 'invoice_id');
}
}
The additional parameters indicate the pivot table name, the column name for the Product model identifier, and the column name for the Invoice model identifier, respectively.
Update your Invoice model. You didn't paste it here, but I'll assume it has a relationship for invoice details. If not, well, oops! Because an invoice can belong to many products, essentially the inverse of the products relationship we just defined, it's defined it pretty much the exact same way.
class Invoice extends Eloquent
{
public function products()
{
return $this->belongsToMany('Product', 'invoice_details', 'invoice_id', 'product_id');
}
}
You now have a many-to-many relationship between Products and Invoices, that is retrieved using intuitive relationship methods! Huzzah.
Hey wait, where's my quantity?
You'll have to figure that one out on your own. :)
Got the answer (there is 2 hours of my life I'm never getting back) I had to manually add the fk and pk. So in my InvoiceDetails model it should have looked like this
public function products()
{
return $this->belongsTo('Product', 'product_id', 'id');
}

Categories