Laravel BelongsToMany Pivot Table : How to fetch selected columns - php

Want to get selected columns, when querying through pivot table. Following is my scenario.
I have 3 tables,
coupons
coupon_cities
cities
relationship details are as following.
class Coupon extends Eloquent {
public function cities(){
return $this->belongsToMany('City', 'coupon_cities', 'coupon_id', 'city_id');
}
}
When I query
Coupon::with('cities')
it returns array of all columns of city table for each entry of coupon row

The only way is this:
$coupon = Coupon->first();
$coupon->cities()->get([your columns here]);
Normally you'd do it like below:
Coupon::with(['cities' => function ($q)
{
$q->select('column', 'column2' ...);
}
However it won't work for belongsToMany relation -> https://github.com/laravel/framework/pull/4440

Related

Delete specific row from pivot table

I have a 2 tables (Gifts, Campaigns) that both have BelongstoMany relation:
Relations:
Campaign relation:
public function gifts(){
return $this->belongsToMany(Gift::class, 'campaign_gift');
}
Gift relation:
public function campaign(){
return $this->belongsToMany(Campaign::class, 'campaign_gift');
}
I am trying to delete a specific row from a pivot table, but with my current implementation, it deletes all of the rows, that have matching id's. Important note, that a single campaign can have multiple same gift, therefore, gift's id can be repeated within the same campaign, making the table having duplicate records.
Example of a pivot table:
Current Controller:
function deleteGiftsFromCampaign($id)
{
$gift = Gift::find($id);
$gift -> campaign() -> detach();
return back();
}
Is there a way to implement a specific row deletion, without creating extra columns within the pivot table?
$gift = Gift::find($id);
$gift -> campaign()->detach($gift_id);

How to Join Eloquent and Query Builder in one query statement in laravel

I have 2 queries that needed to join 1st is eloquent and 2nd is query builder,
1st Query
$products = Product::all();
2nd Query
$inventory = DB::table('product_warehouse')
->where('product_id', $product_id)
->where('warehouse_id', $warehouse_id)
->first();
How to merge this 2 queries into elouquent way ?
From your usage of the query builder it seems like you have an intermediate table to store which product to which warehouse exist, but if it is a one to many relationship you should not have that table, instead in your products table you should have a warehouse_id which will reference the id on the warehouses table, as you said the relationship is one to many, not many to many.
So in your Warehouse model you can add:
public function products()
{
return $this->hasMany(Product::class);
}
And in your Product model:
public function warehouse()
{
return $this->belongsTo(Warehouse::class);
}
Based on your table name, you might need to set the $table in your warehouse model to match that:
protected $table = 'product_warehouse';
Then you have many ways to fetch it, one of which is :
Warehouse::find($warehouse_id)->products;
// or
Warehouse::with('products')->where('id', $warehouse_id)->get();
// to get the warehouse to which the product belongs to
Product::find($product_id)->warehouse;

Sum pivot table field on Eloquent many-to-many relationship

I have an orders table, an items table, and a pivot table called item_order which has two custom fields (price, quantity). The relationship between Order and Item is belongsToMany. I'm trying to return the count of all items with an id of 1, where the parent Order->status == 'received'. For the life of me, I can't figure out how to do this.
class Order extends Model
{
public function items()
{
return $this->belongsToMany(Item::class)->withPivot('price', 'quantity');
}
}
class Item extends Model
{
public function orders()
{
return $this->belongsToMany(Order::class)->withPivot('price', 'quantity');
}
}
Try this:
$total_quantity = Item::find(1) // getting the Item
->orders() // entering the relationship
->with('items') // eager loading related data
->where('status', '=', 'received') // constraining the relationship
->get() // getting the results: Collection of Order
->sum('pivot.quantity'); // sum the pivot field to return a single value.
The strategy here is to find the desired Item to then get the related Orders to this Item that has a 'received' status, to finally sum the pivot attribute in order to get a single value.
It should work.
Considering you know the id of the item, most performant way would be to query item_order table directly. I would create a pivot model for ItemOrder and define the belongsTo(Order::class) relationship and do this:
$sum = ItemOrder::where('item_id', $someItemId)
->whereHas('order', function ($q) {
return $q->where('status', 'received');
})
->sum('quantity');

how to use where for relationship in laravel eloquent?

I want to use where clause on the another relationship not my current selecting model as below table
table Customer
-------id-----customer_name
Table ModelA
table Customer
-------id-----fk_custome_id
table ModelB
-------id-----fk_ModelA_id
Function in Controller
$data['data'] = customer::with(['modelA','modelA.modelB'])
->where('fk_customer_id', 2)->get();
Customer Model
final function ModalA (){
return $this->hasMany('App\Models\ModelA', 'fk_customer_id', 'id');
}
ModelA Model
final function Modelb (){
return $this->hasMany('App\Models\ModelB', 'fk_modelA_id', 'id');
}
Error:
I will got error as below because select sql don't find the column name fk_customer_id in table customer, So how can I user fk_customer_id (in table ModelA) for where.
You can useYou can use whereHas like:
$data['data'] = customer::with(['modelA','modelA.modelB'])
->whereHas('modelA', function ($query) {
$query->where('fk_customer_id', 2);
})->get();
It's because when you're using with you just eager load constrints but you won't attach it to the main query (of the customer model). So there are two way: one modern with using whereHas or using join queries.

Eloquent many to many relationship access table column value from pivot table

I have two models:
class Order extends Eloquent
{
public function User()
{
return $this->belongsTo('User');
}
public function Product()
{
return $this->belongsToMany('Product');
}
}
and the second one is:
class Product extends Eloquent
{
public function Order()
{
return $this->belongsToMany('Order');
}
}
My question is how can i access a value of second table column using pivot table:
product table:
id
title
image
order table:
id
status
pivot table(order_product):
id
product_id
order_id
I need to access title column of products from orders. for example if a user orders many products in one order I can fetch all product title and show theme.
I don't like use join , instead I like to use Laravel functionality itself.
I found the answer:
$orders = Order::orderBy('created_at', 'DESC')->paginate($page_number);
foreach($orders as $item){
foreach($item->product as $item){
{{$item->title}}<br>
}
}
I can access products from order.

Categories