Eloquent relation pivot table with table - php

I read the laravel documentation but I couldn't understand very well.
I have this structure on my database.
PriceTable - which contains info about the period of promotional prices and the default price.
Product - which contains info about products.
and PriceTable_Product - which contains the foreign keys of Product and PriceTable and the respective price.
Example:
PriceTable | PriceTable_Product | Product
id | description | PriceTable_id | Product_id | price | product_id| name
1 | default | 1 | 1 | 5.00 | 1 | test
2 | promotional | 2 | 1 | 3.50 |
And at the Order table I can have multiples products, so I want to know if it is possible to relation Order table, with the pivot table PriceTable_Product, because I need the information of which table belongs the price when the product was sold.

First of all you may define the relations between Product and PriceTable.
Product model (App\Product.php)
<?php
namespace App;
class Product extends Model {
protected $table = 'products';
//if the default primary key isn't 'id' you may use $primaryKey
protected $primaryKey = 'product_id';
public function pricetables() {
return $this->belongsToMany('App\PriceTable');
}
}
PriceTable model (App\PriceTable.php)
<?php
namespace App;
class PriceTable extends Model {
protected $table = 'pricetable';
public function products() {
return $this->belongsToMany('App\Product');
}
}
If you created the relations then you can use:
$product = App\Product::find(1);
foreach ($product->pricetables as $pricetable) {
echo $pricetable->pivot->description;
}

Related

Laravel Multiple Relationship for a sum column

I have Three Models name Invoices, Invoiceitems and Products.
Each Invoices HasMany Relationship with Invoiceitems Model.
Each Invoiceitems HasOne Relationship with Products Model.
I need to sum of Invoiceitem product amount where the Product has category 4.
Table Structure
Invoice
id | date | total_amt
Invoiceitem
id | invoiceid | product_id | product_amt | quantity | total_amt
Product
id | product_name | category_id
Relationship
Invoice Model
public function invoiceitems()
{
return $this->hasMany('App\Invoiceitems', 'invoiceid', 'id');
}
Invoiceitem Model
public function products()
{
return $this->hasOne('App\Products', 'id', 'product_id');
}
Expected Report
Invoice No | Date | Veg Category Product Amt | NonVeg Category Product Amt | Total Amt
KL0001 | 15-05-2021 | 0.00 | 190.366 | 190.366
KL0002 | 16-05-2021 | 20.00 | 350.000 | 370.000
Currently we use following Helper Function to get Particular category Products Total Amount
function getInvdiscsumamt($inv_id, $prdtype)
{
$totaldisamt = Invoiceitems::Where('invoice_id', $inv_id)->whereHas('products', function ($query) use ($prdtype) {
$query->where('category_id', $prdtype);
})->sum('total_amt');
return $totalpdtamt;
}
How to display particular category products total amount using Elequoent method
You can try one of the aggregate functions that already exist in Eloquent, see https://laravel.com/docs/8.x/eloquent-relationships#other-aggregate-functions, for instance withSum:
$invoiceItem = InvoiceItem::query()
->where('invoice_id', $invId)
->withSum(['products', function($query) use ($productType) {
$query->where('category_id', $productType);
}, 'frequency'])
->first();
Your property will then be available using the property {relation}_{function}_{column}, so in this case products_sum_frequency.
Note that the withSum does not share anything with the with (or whereHas) function, that means that if you use a subselection in your query like ->with(['products', function($query){...}]) that will be a separate selection from the withSum query.
I also recommend to use proper camelcasing in your functions and also your models. I'd also use singular names for all your model class names. So Invoiceitems would become InvoiceItem (models/InvoiceItem.php). This is the default way to define it in laravel as far as I'm aware.

Product with Multiple Product Related using Laravel Model HasMany() & BelongsTo?

As of now I have 2 different Model
ProductModel.php Which is my list of products.
ProductRelated.php Which is the assigned related product per specific product.
The scenario is,
If I have id = 1 in my ProductModel. id (primary key of Product Model)
and in my ProductRelated.php I have this
prodID (Which is the equivalent of id (primary key of Product Model)
This will serve to identify which specific product id the related products are being assiged.
prodRelatedID this is the products related to that product.
So my ProductModel will have this data
id | prodTitle | prodDesc | More fields here...
1 | Product 1 | Description | More FIeld value here ..
2 | Product 2 | Description | More FIeld value here ..
3 | Product 3 | Description | More FIeld value here ..
In my ProductRelated will have this data
id | prodID | prodRelatedID | More fields here...
1 | 1 | 2 | More FIeld value here ..
2 | 1 | 3 | More FIeld value here ..
Which means, id = 1 from ProductModel has 2 different prodRelatedID
and those are the 2 and 3
My idea by doing this is to use hasMany()
Here's my ProductModel
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\User;
class ProductModel extends Model
{
public $timestamps = true;
protected $table = 'product';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'id',
'prodTitle',
'prodDesc',
'prodCategory',
'attachment',
'prodSize',
'prodPrice',
'created_by',
'is_best_seller',
'prod_included',
'prod_instruction',
];
}
My ProductRelated
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\User;
class ProductRelated extends Model
{
public $timestamps = true;
protected $table = 'product_related';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'id',
'prodID',
'prodRelatedID',
'created_by'
];
}
If you just want to get all related products per specific product, I do not think you need ProductRelated.
In your ProductModel
public function relatedProducts()
{
return $this->belongsToMany(ProductModel::class, 'product_related', 'prodID', 'prodRelatedID');
}
And then you should be able to get all records like this:
$relatedProducts = ProductModel::find(1)->relatedProducts()->get();

Laravel 5.4 | Fetching data from Pivot Table

I have 4 tables in my database:
Table 1: Category
---|------
id | name
---|------
1 | Cars
In 'Category' model class I have defined the following relationship:
class Category {
public function fields() {
return $this->belongsToMany('App\Field');
}
}
Table 2: Field
id | name
---|-------
1 | Make
In 'Field' model class I have defined the following relationship:
class Field {
public function categories() {
return $this->belongsToMany('App\Category');
}
}
Table 3: Field_Options
field_id | value
---------|-------
1 | Audi
1 | BMW
In 'FieldOption' model class I have defined the following relationship:
class FieldOption extends Model
{
public function field() {
return $this->belongsTo('App\Field');
}
}
Table 4: Category_Field
category_id | field_id
------------|-------
1 | 1
Now I need to fetch all the fields and field_options for category_id=1. How can I achieve this using Laravel?
Thanks!
First define relationship between Field and FieldOptions
public function options() {
return $this->hasMany('App\FieldOption');
}
Then you can eager load all relationships like this
$category = Category::with('fields.options')->find(1);
//Get category 1, with all fields and their respectif fieldOptions

Laravel - model modifications

I need to refactor project and I have problem. Below is old, working model, where 'active' column is in "people" table. I need to move 'active' column into "people_translations" table.
Do you have any Idea to modify scopeActive method?
Thanks a lot!
Old working model:
class BaseModel extends Eloquent
{
public function scopeActive($query)
{
return $query->where($this->table . '.active', '=', 1);
}
}
class People extends BaseModel
{
protected $table = 'peoples';
protected $translationModel = 'PeopleTranslation';
}
class PeopleTranslation extends Eloquent
{
public $timestamps = false;
protected $table = 'peoples_translations';
}
Old tables structure:
Table: peoples
id | type | date | active
-------------------------
7 | .... | ... | 1
Table: peoples_translations
id | people_id | language_id | name
-----------------------------------
1 | 7 | 1 | Ann
Old query:
$peoples = \People::active()->get();
New tables structure:
Table: peoples
id | type | date
----------------
7 | .... | ...
Table: peoples_translations
id | people_id | language_id | name | active
--------------------------------------------
1 | 7 | 1 | Ann | 1
Create a relation for translations inside People Model
public function translations()
{
return $this->hasMany('PeopleTranslation', 'people_id');
}
Create active scope in People model
public function scopeActive($query)
{
return $query->whereHas('translations', function($query) {
$query->where('active', 1);
});
}
It will make subquery for this table and as a result it will get where (count of translations with active = 1) > 0.
If you have one-to-one relation - look for hasOne relation method instead of hasMany.

Use relationships without an extra model

I have 2 tables, stores and employees. The employees table is not persons, but just an estimate of the employees in a given store.
store
id | name | fk_employees
1 | Lewis | 2
employees
id | employees_amount
1 | 1-5
2 | 6-10
I could created an EmployeeCount model to define the relationship.
Store extends Eloquent {
public function employees() {
return $this->belongsTo('EmployeeCount');
}
}
EmployeeCount extends Eloquent {
}
However, it looks cluttered to me having to create an empty class.
Can I do this in a smarter way?

Categories