I have a pivot table 'game_genre'(with game_id and genre_id). The game and genre model has a belongsToMany relationship similar to example below.
I have been attempting to gather the games which contain both genre_id of 60 and 55 together. I have been getting the correct result using the following SQL query, but when using the following query builder I end up getting a column not found error when using the having() function.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'genre_id' in 'having clause'
Im not sure how else to structure the query builder?
MODEL:
class Game extends Model
{
public function genres()
{
return $this->belongsToMany('App\Genre');
}
}
SQL:
SELECT *
FROM game_genre
WHERE genre_id = 55 OR genre_id = 60
GROUP BY game_id
HAVING COUNT(DISTINCT genre_id) = 2;
CONTROLLER:
$game = Game::whereHas('genres', function ($query)
{
$query->where('genre_id', '55')
->orWhere('genre_id', '60')
->groupBy('game_id')
->having('genre_id','=', 2);
})->get();
You forgot the aggregate function (in this case COUNT) in your HAVING condition:
$query->where('genre_id', '55')
->orWhere('genre_id', '60')
->groupBy('game_id')
->havingRaw('COUNT(DISTINCT genre_id) = 2');
Instead of adding several where() and orWhere() to your query, you could also use whereIn() which takes an array:
$myArray = [55,60];
$query->whereIn('genre_id', $myArray)
->groupBy('game_id')
->havingRaw('COUNT(DISTINCT genre_id) = 2');
You can use the following query to get the Games which contain both genre_id of 60 and 55:
$games = Game::whereHas('genres', function ($query) {
$query->where('genre_id', '55');
})
->whereHas('genres', function ($query) {
$query->where('genre_id', '60');
})
->get();
Related
I have 2 models, Service and Category. They are related with a many-to-many relationship like so:
Service.php
public function categories()
{
return $this->belongsToMany('App\Category')->withTimestamps();
}
Category.php
public function services()
{
return $this->belongsToMany('App\Service')->withTimestamps();
}
And of course they're joined by a pivot table:
category_service
- category_id
- service_id
- created_at
- updated_at
I'd like to use local scope to filter service result based on IDs of categories. I've done the following:
Service.php
public function scopeFilter($query, $category_ids)
{
$services = Service::whereHas('categories', function (Builder $query) use ($category_ids) {
$query->whereIn('category_id', $category_ids)->get();
});
return $services;
}
But I'm getting a Column not found error, specifically:
Column not found: 1054 Unknown column 'services.id' in 'where clause' (SQL: select * from `categories` inner join `category_service` on `categories`.`id` = `category_service`.`category_id` where `services`.`id` = `category_service`.`service_id` and `category_id` in (1, 2))
1 and 2 are the category IDs I pass.
I wrote the function based on the answer I found here and here.
Any pointers?
Your error message show that your query is begin with categories and without join services.
So put the ->get() outside the closure.
public function scopeFilter($query, $category_ids)
{
$services = Service::whereHas('categories', function (Builder $query) use ($category_ids) {
$query->whereIn('category_id', $category_ids);
})->get();
return $services;
}
I am using Laravel 5.6 and i have a standard query
Order::where('dict_statuses_id', 1)
->leftJoin('dict_statuses', 'dict_statuses_id', '=', 'dict_statuses.id')
->get();
So i have list of orders with details where status = 1 (new) after join table i see status as New or Complete. Is any way to change this query using whereHas ?
i tried use
Order::whereHas('status', function($q){
$q->where('dict_statuses_id', 1);
})->get();
But no results, in model Order i have
public function status()
{
return $this->hasMany('App\DictStatuses');
}
[Updated]
i have an error:
Column not found: 1054 Unknown column 'dict_statuses.orders_id'
in 'where clause' (SQL: select * from `orders` where exists
(select * from `dict_statuses` where `orders`.`id` = `dict_statuses`.`orders_id` and `dict_statuses_id` = 1)
and `orders`.`deleted_at` is null)
In my table i have table Orders where is field: dict_statuses_id
and table dict_statuses with fields: id, public_name
Why error is about dict_statuses.orders_id
Try Order::has('status')->get();
You can pass in variables to a relationship so you could potentially do.
public function status($id) {
return $this->hasMany(DictStatuses::class)->where('dict_statuses_id', $id);
}
Try defining the local key & foreign key.
$this->hasMany(DictStatuses::class, 'foreign_key', 'local_key');
I think your dict_statuses doesn't have a column called order_id.
Please include that column in your migration
then call
Order::whereHas('status', function($q){
$q->where('dict_statuses_id', 1);
})->get();
in your controller
or change the relation in Order model as
public function status(){
return $this->belongsTo('App\DictStatuses'):
}
I am trying to better at using scopes to make cleaner calls to specific information.
Currently I have a weeks, workouts and week_workout tables. I am trying to get a workout for Carbon->today(). To do this I need to access the date field on the week_workout table.
week_workout
| week_id | workout_id | date
Workout.php
public function weeks(){
return $this->belongsToMany('App\Week')
->withPivot( ['program', 'warmup', 'date'] )
->orderBy('date', 'asc');
}
public function scopeToday($query)
{
return $query->with('weeks')->wherePivot('date', Carbon::today());
}
Controller
$workouts = Workout::today()->get();
When I do this I get `Column not found: 1054 Unknown column 'pivot' in 'where clause' (SQL: select * from `workouts` where `pivot` = date)
I am not sure why its looking for pivot column. The docs seem to suggest it will look for date in the pivot table if I load it with the relationship but it appears I am missing something.
So it looks like you have to use whereHas. I updated the scope to just take any date to make it more powerful:
public function scopeDate($query, $date)
{
return $query->whereHas('weeks', function ($q) use($date){
$q->where('date', $date);
});
}
then in the controller:
$workouts = Workout::date( Carbon::today() )->get();
I have three tables, settlements table hasMany add_members table and ciphers table hasMany add_members table. In Settlement and Cipher Model I put function:
public function members()
{
return $this->hasMany('App\AddMember');
}
so now, when I need count how many rows in add_members table I have but with reon_id in settlements table I did like this:
$first_count = Settlement::where('town_id', Auth::user()->town_id)
->with('members')
->where('reon_id', '1')
->count();
and that working, but now I need second count which also counting add_members rows with reon_id == 1 in settlements table but woth one more relationships where cipher == 0 in ciphers table. If I do with belongsTo relationship through AddMember Model I'm getting error:
(2/2) QueryException
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'reon_id' in 'where clause'
$second_count = Settlement::where('town_id', Auth::user()->town_id)
->with('members')
->where('reon_id', '1')
->Cipher::with('members')
->where('cipher', '0')
->count();
I know that this second is wrong but I don't know hot to get with reon_id == 1 in Settlement model and cipher == 0 in Cipher model...
Laravel relation table query
$first_count = Settlement::where('town_id', Auth::user()->town_id)
->with(['members', function ($q) {
$q->where('reon_id', 1);
}])->get();
or
$first_count = Settlement::with('members')->where('town_id', Auth::user()->town_id)
->whereHas('members', function ($q) {
$q->where('reon_id', 1);
})->get();
Have you tried it this way, so eloquent know which column is in which table?
$users = App\User::with(['posts' => function ($query) {
$query->where('title', 'like', '%first%');
}])->get();
Or type additional Info about columns like this:
App\Book::with('author:id,name')->get();
More in laravel docs
I have 2 tables.
Products
Brands
Im trying to return top 10 brand models with the most products.
I've tried.
Product::select('brand', DB::raw('count(brand) as count'))->groupBy('brand')->orderBy('count','desc')->take(10)->get();
But that doesn't return the hole model and only returns
Brand
Count
I've also tried
return $brands = Brand::whereHas('products', function($q) {
$q->count() > 10;
})->get();
But I get the error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'brands.id' in
'where clause' (SQL: select count(*) as aggregate from products
where brands.id = products.brand)
My Brand Model
public function products()
{
return $this->hasMany('App\Product','brand');
}
My Product Model
public function manuf()
{
return $this->belongsTo('App\Brand','brand');
}
try this:
$brands = Brands::has('products', '>' , 10)->with('products')->get();
You should be able to accomplish this with the withCount method if you're using at least Laravel 5.3:
Brand::withCount('products')->orderBy('products_count', 'DESC')->take(10)->get();
Where products is the name of your relation. This will give you a new field in your query, products_count that you can order by.