I have Products table and Categories table.
Each of products may have one or more cateories. For this I created table: products_caetgories.
So, how I can to set where condition where product_category = 1?
I tried like as:
Product::with("categories")->where("product_category", 1)->get();
takle a look at whereHas
you may use the whereHas and orWhereHas methods to put "where"
conditions on your has queries. These methods allow you to add
customized constraints to a relationship constraint, such as checking
the content of a comment:
Product::with("categories")->whereHas("categories", function($query){
$query->where('id','=',1);
})->get();
Related
I have two database tables items and measurement_units - item has measurement unit.
Now the problem is I want to select a particular column from items and some column from measurement_unit. I want to use Eager loading
e.g.
$items_with_mu = Item::with("measurement_unit")->select(["item_name", "item_stock"])->first();
When accessing measurement_unit. It returns null. Without the select function it returns data(measurement_unit).
$items_with_mu->measurement_unit;
can anyone help me and sorry for my English.
Try this
Item::with(['measurement_unit' => function($q) {
$q->select('id','unit_column'); //specified measurement_unit column
}])
->select('id','measurement_unit_id','item_name')
->get();
If your laravel version is >=5.5 then you can write in a single line
Item::with('measurement_unit:id,unit_column')
->select('id','measurement_unit_id','item_name')
->get()
You have to select the primary column of the main model like below.
items_with_mu = Item::with("measurement_unit")->select(["item_name", "item_stock", "primary_key"])->first();
in a Laravel application, I have a list of companies. Some of those are related to a subscriptions table in a 1 x n relation.
I want to order the companies in a way that the ones which have a subscription appear before the ones which have no subscription using just one db query.
Any idea is much appreciated!
thanks!
Laravel uses separate queries to eager load relationships. So if you want to do this you will need to join the tables and order by...
Something in the form...
$companies = App\Companies::join('subscriptions as sub', 'sub.company_id', '=', 'company.id')
->orderBy('sub.somefield', 'DESC')
->select(what you need)
->with('if you need the relation data');
You know you can also only query those records that have a relationship with
$companies = App\Companies::has('subscription')->get();
Maybe that is all you need... and
$companies = App\Companies::doesntHave('subscription')->get();
... returns the opposite where the company has no subscription...
I currently have the following:
Cars::with('cases')->with(['parts', 'parts.engines', 'parts.engines.metals'])
->orderBy('car_name', 'DESC')->orderBy('id', 'DESC');
The above will list all rows in my cars table along with the metal associated with the engine in each of those cars. The metals table is related to the cars table through the parts and then the engines tables.
I've tried using:
Cars::with('cases')->whereHas(['parts', 'parts.engines', 'parts.engines.metals'], function($query){
$query->where('weight', '=', 45)
})->orderBy('car_name', 'DESC')->orderBy('id', 'DESC');
But this errors out since whereHas() does not accept an array for its first parameter and I don't see a way to link to distant relationships with it.
How do I apply a WHERE conditional on a column in the metals table using the built-in ORM?
whereHas() only needs the name of the relationship for which you'd like to add the conditions. So, if you're trying to add the condition to the metals, you just need to restrict the parts.engines.metals relationship.
On a side note, when you eager load nested relationships, you don't need to also specify to load the intermediate relationship. That is, when you eager load parts.engines, you don't need to also eager load parts.
So, your query would look something like:
Cars::with(['cases', 'parts.engines.metals'])
->whereHas('parts.engines.metals', function($query) {
$query->where('weight', '=', 45)
})
->orderBy('car_name', 'DESC')
->orderBy('id', 'DESC');
This query will only retrieve cars that have a related metal with a weight of 45. Additionally, for those cars that are retrieved, it will also eager load all of the cases, parts, engines, and metals related to those cars.
I think you mean this:
Cars::with(['cases', 'parts', 'parts.engines', 'parts.engines.metals' => function($query){
$query->where('weight', '=', 45);
}])->orderBy('car_name', 'DESC')->orderBy('id', 'DESC');
I have four models: Item, Car, ItemLocation and Branch.
An Item has a Car and a ItemLocation via a person_id and a item_location_id field in the DB.
A Car has a branch_id which links to Branch, and an ItemLocation also has a branch_id in the same way.
What I want to do is to select all Items where their Cars's branch is not equal to their ItemLocation's branch.
I tried this statement, though I knew that it wouldn't work:
Item::with('car','item_location')
->where('car.branch_id', '<>', 'item_location.branch_id')
->get();
I'm aware of querying on relationships, but don't understand how to do that across relationships like this.
Any ideas?
Querying relationships won't help you, since you want to compare values from separate tables. You need joins:
$items = Item::select('items.*')
->join('item_locations as il', 'il.id', '=', 'items.item_location_id')
->join('cars', function ($j) {
$j->on('cars.person_id', '=', 'items.id')
->on('cars.branch_id', '<>', 'il.branch_id');
})
->get()
This will fetch all the items having both cars and item_location and matching your criteria. If you want to include also ones that don't have either of the relations, then use leftJoins instead and whereNull('cars.id')
ps. It's hard to read your question. Instead of describing these relationships, better simply show the tables with relevant fields.
Some help with many to many relationships in Laravel:
Using the example for roles and users - basically:
a table for all the roles
a table for the users
and table with user_id and role_id.
I want to add to the third table, eg Year. basically the pivot table will have user_id, role_id and year_id.
I want to be able to make a query to pull for example all users assigned a specific role in a specific year. Eg All users with role_id = 2, and year_id = 1.
Any help will be appreciated
Before answering, I would like to suggest you not to put year on database like this.
All your tables should have created_at and updated_at which should be enough for that.
To filter users like you want. You could do this:
// This queries all users that were assigned to 'admin' role within 2013.
User::join('role_users', 'role_users.user_id', '=', 'users.id')
->join('roles', 'roles.id', '=', 'role_users.role_id')
->where('roles.name', '=', 'admin')
->where(DB::raw('YEAR(role_users.created_at)', '=', '2013')
->get();
This example may not be the precise query you are looking for, but should be enough for you to come up with it.
The best way to achieve a three way relation with Eloquent is to create a model for the table representing this relation. Pivot tables is meant to be used for two way relations.
You could have then a table called roles_users_year which could have data related to this 3 way relation like a timestamp or whatever...
A very late answer to a very old question, but Laravel has supported additional intermediate (pivot) table columns of at least Laravel 5.1 judging from the documentation, which hasn't changed at least through Laravel 6.x.
You can describe these extra columns when defining your many-to-many relationship:
return $this->belongsToMany(Role::class)->withPivot('column1', 'column2');
or in your case, the below would also do the job:
return $this->belongsToMany(Role::class)->withTimestamps();
which you can then access via the pivot attribute on your model:
$user = User::find(1);
foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}
Note that the pivot attribute is on the distant relationship model (a single Role) and not on the relationship itself.
To get all the Roles assigned to Users in any given year, you might create a special relationship:
// User.php
public function rolesInYear($year) {
return $this->belongsToMany(Role::class)
->wherePivot('created_at', '>=', Carbon::create($year))
->wherePivot('created_at', '<', Carbon::create($year + 1));
}