Query Laravel Relationship - laravel

I have 3 Model
In Purchase Model
protected $fillable = [
'name', 'date', 'description', 'active', 'supplier', 'total', 'paid', 'purchase_status', 'payment_status',
];
public function product()
{
return $this->belongsTo(\App\Product::class);
}
public function order()
{
return $this->belongsTo(\App\Order::class);
}
In Order Model
protected $fillable = [
'name', 'quantity', 'unit_cost', 'discount', 'tax', 'sub_total'
];
public function order_items()
{
return $this->belongsTo(\App\OrderItem::class);
}
In my OrderItem Model
protected $fillable = ['active', 'description', 'quantity', 'discount', 'unit_price'];
public function order()
{
return $this->belongsTo(\App\Order::class);
}
Is it possible to query Order_Items From Purchases trough Orders Relationship in Laravel?

Oh, i found my answer...
In Order Model
i changed belongsTo to hasMany
protected $fillable = [
'name', 'quantity', 'unit_cost', 'discount', 'tax', 'sub_total'
];
public function order_items()
{
return $this->hasMany(\App\OrderItem::class);
}

Yes you can write this relations in your models and write the query like this:
Purchase
public function order()
{
return $this->belongsTo('App\Models\Order', 'order_id', 'id');
}
Order_Item
public function order()
{
return $this->belongsTo('App\Models\Order', 'order_id', 'id');
}
Order
public function order_items()
{
return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}
public function purchases()
{
return $this->hasMany('App\Models\purchase', 'order_id', 'id');
}
Now you can use this query:
$purchase = \App\Models\Purchase::first();
$order_items = $purchase->order->order_items;

I see that you've fixed the relationship Order -> OrderItem of belongsTo to hasMany. But the question was also about how to query through relationships so I'll just add up to this so it could be useful to other users here.
Now you could do
$order_items = $purchase->order->order_items
to get the order items of the purchase.
However you should consider that this would execute further queries to the DB. One for fetching the order and then another one for fetching the order_items. If you're looping through a list of purchases, this could escalate quickly and end up making too much DB queries and affect the performance of your application.
The solution is eager loading.
You could do either pre-fetch the order and items along with the purchase like this:
$purchase = Purchase::with('order.order_items')->find(1);
or if you've already fetched the purchase, then you could do:
$purchase->load('order.order_items');
Then when getting the order items in your code like this
$purchase->order->order_items, you have no additional queries to the DB.

Related

laravel belongstomany same table Not unique table/alias

laravel belongstomany same table error: Not unique table/alias. Help me please.
class Categories extends Model
{
use HasFactory;
protected $fillable = [
'name',
'parent_id',
'slug',
'title',
'description'
];
public function categories(){
return $this->belongsToMany(Categories::class, 'categories', 'id', 'parent_id' );
}
}
Without second table you can have many-to-many relationship. You may try one-to-many with something like this:
class Categories extends Model
{
/* ... */
public function parentCategory() {
return $this->belongsTo(Categories::class, 'parent_id' );
}
public function subCategories() {
return $this->hasMany( Categories::class, 'parent_id');
}
}

Laravel Eloquent query relations with 3 levels

I want some help of forming queries on Laravel Eloquent
I have 4 models in my application
Item Model
class Item extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'code', 'name', 'type', 'price', 'cost', 'reorder_level', 'status'
];
public function grnoteitems()
{
return $this->hasMany(Grnoteitem::class);
}
}
Grnote Model
class Grnote extends Model
{
use HasFactory;
protected $fillable = [
'date', 'number', 'warehouse_id','user_id', 'authorized_id', 'approved_id', 'notes'
];
public function grnoteitems()
{
return $this->hasMany(Grnoteitem::class);
}
public function warehouse()
{
return $this->belongsTo(Warehouse::class);
}
}
Grnoteitem Model
class Grnoteitem extends Model
{
use HasFactory;
protected $fillable = [
'grnote_id', 'item_id', 'description', 'packing', 'quantity', 'price', 'total'
];
public function grnote()
{
return $this->belongsTo(Grnote::class);
}
public function item()
{
return $this->belongsTo(Item::class);
}
}
Warehouse Model
class Warehouse extends Model
{
use HasFactory;
protected $fillable = ['name', 'address'];
public function grnotes()
{
return $this->hasMany(Grnote::class);
}
}
Quantity of the item is calculated by multiplying quantity and packing columns in the grnotes table.
Now I want to retrieve all the items with their quantity(quantity * packing) from a particular warehouse.
I tired the below query
$items = Item::withSum('grnoteitems', 'quantity', function($query) use($warehouse, $from, $to){
$query->with('grnote', function($query1) use($warehouse, $from, $to){
$query1->where('warehouse_id', $warehouse->id)
->whereBetween('date', [$from, $to])->get();
})->get();
})->get();
This is working fine. But I don't find any way to get sum of two multiplied columns
I want something like
$items = Item::withSum('grnoteitems', '(quantity * packing)', function($query) use($warehouse, $from, $to){
$query->with('grnote', function($query1) use($warehouse, $from, $to){
$query1->where('warehouse_id', $warehouse->id)
->whereBetween('date', [$from, $to])->get();
})->get();
})->get();
Please help me to solve this.
It's a bit long to write all the code to do this, but my idea would to :
start your query from the wareHouse you want items from
so Warehouse::first() [with grnote [with item]] and custom where stuff
then the data you need to calculate are on the pivot table between Item and Grnote, so I would add withPivot to both relations
in this query order, the pivot value will be appended as a relation to the Item object
I would add a new attribute to the item model. Checking if the pivot attribute is set (so it comes from a query with pivot), calculate the quantity, and append it to the Item instance
You can also loop on the resulting Collection to append your new attribute.

Laravel - How to do referenctial integrity with where clause

In Laravel-8, I have this models:
Licence:
protected $fillable = [
'id',
'number',
'employee_id',
'is_active',
];
public function employee()
{
return $this->belongsTo(Employee::class,'employee_id','id');
}
Employee:
protected $fillable = [
'id',
'first_name',
'last_name',
'other_name',
];
public function licences()
{
return $this->hasMany(DriverLicence::class);
}
Employee can have more than one licence. But only one can be active.
I have this in the controller:
$employee = Employee::with('licences')->get();
How do I add where clause in the referential integrity that it should be licence where is_active is 1?
Thank
you can use whereHas() to use condition in relation model.
$employee = Employee::with('licences')
->wherehas('licences',function($q){
$q->where('is_active',1);
})
->get();
You can also do by adding relation and condition to get active licence
public function activeLicence()
{
return $this->hasOne(DriverLicence::class,'employee_id')->where('is_activce',1);
}
You can access active licence as below:
$employee->activeLicence;

Search in Laravel relation using json column

I have problem with search in json column.
I have 3 relations:
products
feature products
feature_values
My tables:
products: https://ibb.co/1dgjT6m
feature products: https://ibb.co/K9f74Wn
feature_values: https://ibb.co/rc3zG5W
My migrations:
Product:
class Product extends Model implements Presentable
{
....
public function featureProducts()
{
return $this->hasMany(FeatureProduct::class, 'product_id');
//return $this->belongsToMany(Feature::class, 'feature_product', 'id');
}
}
FeatureProduct
class FeatureProduct extends Model
{
protected $table = "feature_product";
protected $with = [
'values'
];
public function values()
{
return $this->belongsTo(FeatureValue::class, 'feature_values_ids', 'id');
}
}
FeatureValues:
class FeatureValue extends Model
{
use SoftDeletes,
Translatable;
protected $fillable = [
'feature_id',
'value'
];
protected $dates = [
'created_at',
'updated_at',
'deleted_at'
];
protected $translatable = [
'value'
];
public function feature(): BelongsTo
{
return $this->belongsTo(Feature::class);
}
public function getAdminUrlAttribute(): AbstractAdminUrlPresenter
{
return new FeatureValueUrlPresenter($this);
}
}
I need to show products with features and assigned features_values
I heve problem with search in json column: feature_product. feature_values_ids
When I have INT in this column, then this is working fine:
public function values()
{
return $this->belongsTo(FeatureValue::class, 'feature_values_ids', 'id');
}
When I have:
["1", "2","3"]
I haven't any results :(
Haw can I repair it?

How to count and sum inner relational model in laravel

I am building a small application in Laravel where I got stuck with the sum of inner relational data,
I have a model Company which has Many relation associatedProjects and associatedProjects belongs to relation project and project hasOne technicalDescription.
Company Model:
class Company extends Model {
public function roles()
{
return $this->belongsToMany('Noetic\Plugins\Conxn\Models\Variables\Company\Role', 'company_role_relation', 'company_id', 'role_id')->withTimestamps();
}
public function specialisations()
{
return $this->belongsToMany('Noetic\Plugins\Conxn\Models\Variables\Company\Role', 'company_specialisation_relation', 'company_id', 'specialisation_id')->withTimestamps();
}
public function associatedProjects()
{
return $this->hasMany('Noetic\Plugins\Conxn\Models\Project\AssociateCompany','company_id','id');
}
}
AssociateCompany Model:
class AssociateCompany extends Model {
protected $table = 'project_associate_company';
protected $fillable = [
'project_id', 'company_role_id', 'company_specialisation_id', 'company_id', 'link', 'file_name'
];
public function project()
{
return $this->belongsTo('Noetic\Plugins\Conxn\Models\Project','project_id','id');
}
public function company()
{
return $this->belongsTo('Noetic\Plugins\Conxn\Models\Company','company_id','id');
}
public function companyRole()
{
return $this->belongsTo('Noetic\Plugins\Conxn\Models\Variables\Company\Role',
'company_role_id','id');
}
public function specialisation()
{
return $this->belongsTo('Noetic\Plugins\Conxn\Models\Variables\Company\Role',
'company_specialisation_id','id');
}
}
Project Model
class Project extends Model {
protected $fillable = [
'user_id','koshy_id', 'name', 'slug', 'owner_spv', 'spv_link', 'latitude', 'longitude',
'landmark', 'city', 'district', 'state', 'pin_code', 'region_id', 'country', 'building_use',
'sector', 'conxn_id', 'parent_project_id', 'website', 'project_logo', 'tracked', 'verified',
'code_link', 'status', 'active', 'premium','area'
];
public function technicalDescription()
{
return $this->hasOne('Noetic\Plugins\Conxn\Models\Project\TechnicalDescription','project_id','id');
}
public function associateCompany()
{
return $this->hasMany('Noetic\Plugins\Conxn\Models\Project\AssociateCompany','project_id','id');
}
}
Now this technicalDescription has fields construction_cost, now I want to first count total number of associatedProject and fetch sum of all the project's construction_cost which is in technicalDescription, some what I have done this code:
$company = Company:: where( 'status', 'saved')
->withCount( 'associatedProjects' )
->with('associatedProjects.project.technicalDescription')
->get()
->transform(function ($value) {
$value['project_value'] = $value['associatedProjects']->flatten(2)
->pluck('project.technicalDescription')->sum('construction_cost');
return $value;
})
->sortByDesc('project_value')
->forpage( $request->page , 10 );
$next = $request->page+1 ;
$previous =$request->page-1 ? abs($request->page-1):1 ;
I am unable to use paginate over here as laravel collection doesn't have such method, moreover the query logic also doesn't appear accurate.
Any suggestions are welcome. Thanks
You can use a BelongsToMany relationship to get the technicalDescriptions directly:
class Company extends Model {
public function technicalDescriptions() {
return $this->belongsToMany(
'Noetic\Plugins\Conxn\Models\Project\TechnicalDescription',
'project_associate_company',
'company_id',
'project_id',
null,
'project_id'
);
}
}
$company = Company::where('status', 'saved')
->withCount(['technicalDescriptions as project_value' => function($query) {
$query->select(DB::raw('sum(construction_cost)'));
}])
->orderByDesc('project_value')
->paginate();

Resources