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);
Related
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;
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');
There are 3 models:
First (first_id)
Connection (connection_id, first_id, product_id)
Second (second_id, product_id)
I would like to connect the three models together using laravel relationships
First->joined to Connection though first_id
Connection->joined to First through first_id, & joined to Second through product_id
Second -> joined to Connection through product_id
So: First joined to Second through Connection first_id, product_id
Is this possible to do using something like HasManyThrough?
Thanks for your time
On your First model:
public function second () {
return $this->hasManyThrough(
Second::class,
Connection::class,
'product_id', // Foreign key on connection table
'product_id', // Foreign key on second table
'first_id', // Local key on first table
'first_id' // Local key on connection table
);
}
Based on your description the column names should work.
In tinker you can validate if it's hooked up correctly by doing something like First::first()->second.
It depends on what type of relationship Your first model and second model shares as well as what type of relation second and third model shares.
if consider your first model First and second model Second shares a one-to-one relation, as well as Second model and Third models shares one-to-one relationships.
It will be $first->second->third; //no has many through relationship requires
If your First model and Second models shares as hasMany-belongs to relation than you need to use hasManyThrough relationship
example from doc
class Country extends Model
{
public function posts()
{
return $this->hasManyThrough(
'App\Post',
'App\User',
'country_id', // Foreign key on users table...
'user_id', // Foreign key on posts table...
'id', // Local key on countries table...
'id' // Local key on users table...
);
}
}
You can try using nested relationships.
Nested Eager Loading
To eager load nested relationships, you may use "dot" syntax. For example, let's eager load all of the book's authors and all of the author's personal contacts in one Eloquent statement:
$books = App\Book::with('author.contacts')->get();
Book Model:
public function author()
{
return $this->hasOne('App\Author');
}
Author Model:
public function contacts()
{
return $this->hasMany('App\Author');
}
Documentation:
https://laravel.com/docs/5.8/eloquent-relationships
So im creating a booking system where you can create maps and assign them to an event. I have 3 tables to handle this, events, maps, and event_maps
I have after reading the Laravel Documentation i decided to set up a belongsToMany relation.
But when i try to retrieve my maps thru my event model i only get one the first row.
in my controller i do
public function displayForm($id)
{
$event = EventModel::find($id);
print_r($event->maps);
}
The result is a Illuminate\Database\Eloquent\Collection Object with the last out of 2 maps, and i can't for my life figger out how to get them all.
My EventsModel
public function maps()
{
return $this->belongsToMany('App\Models\Booky\MapsModel',
// Table name of the relationship's joining table.
'event_maps',
// Foreign key name of the model on which you are defining the relationship
'map_id',
// Foreign key name of the model that you are joining to
'event_id'
);
}
My MapsModel
public function event()
{
return $this->belongsToMany('App\Models\Booky\EventsModel',
// Table name of the relationship's joining table.
'event_maps',
// Foreign key name of the model on which you are defining the relationship
'event_id',
// Foreign key name of the model that you are joining to
'map_id'
);
}
The database looks something like this
events
- id
- lots of irrelevant data
maps
- id
- lots of irrelevant data
event_maps
- id
- event_id
- map_id
I was thinking that perhaps i should use another relation type, but as far as i understand they don't use a relation table like event_maps.
Everything else work as expected.
Anyone who could clear up this mess? :)
The ids are inverted in the relation. Try this:
public function maps()
{
return $this->belongsToMany('App\Models\Booky\MapsModel',
// Table name of the relationship's joining table.
'event_maps',
// Foreign key name of the model that you are joining to
'event_id'
// Foreign key name of the model on which you are defining the relationship
'map_id',
);
}
And:
public function event()
{
return $this->belongsToMany('App\Models\Booky\EventsModel',
// Table name of the relationship's joining table.
'event_maps',
// Foreign key name of the model that you are joining to
'map_id'
// Foreign key name of the model on which you are defining the relationship
'event_id',
);
}
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