When I apply the wherePivot 'directly' it works, but when I apply it in a when clause it doesn't. I get the error: Column not found: 1054 Unknown column 'pivot' in 'where clause'
return Company::where('owner_id', auth()->user()->id)
->with(['subscribers' => function ($q) {
$q->wherePivot('is_customer', 1); // This works
$q->when($this->type != 'all', function ($q) {
$q->wherePivot('is_customer', 1); // This does not
});
$q->when($this->example != 'all', function ($q) {
$q->where('example', 1); // This works
});
}
])
->firstOrFail();
Your first issue was using the same variable $q as the inner and outer query:
Company::where(/* ... */)->with(['subscribers' => function ($q) {
$q->when($this->type != 'all', function ($q) {
// ...
});
});
In the 1st instance, $q is a belongsToMany, as public function subscribers() in Company.php is a Many-to-many relationship, likely defined as return $this->belongsToMany(Subscriber::class); (or similar). When you call $q->wherePivot(/* ... */), this executes a query against the Pivot table's data.
In the 2nd instance, $q is a basic Builder instance. When you call $q->wherePivot(/* ... */), this executes a "magic method" query, available on all Eloquent Models. where{Column}(), like whereId(), whereEmail(), wherePivot(), etc., will execute an equivalent query like WHERE id ..., WHERE email ... and finally WHERE pivot .... Since you don't have a column called pivot this fails.
The solution here is to not use the same variable name, and pass it forward when querying:
return Company::where('owner_id', auth()->user()->id)
->with(['subscribers' => function ($query) {
$query->when($this->type != 'all', function ($subQuery) use ($query) {
$query->wherePivot('is_customer', 1);
});
])
->firstOrFail();
Now, you can clearly see which instance wherePivot() is being called on, $query being the belongsToMany() query, and $subQuery being a Builder instance, and isn't directly used.
Related
I defined a scope function in an Eloquent model that uses withCount in the query, I also define an unit test for this function that works properly but when I use it in my controller it throws the exception error which is
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'unused_count' in 'where clause' (SQL: select * from `coupons` where `unused_count` > 0)
Here are my eloquent model functions:
public function unsed(): BelongsToMany
{
return $this->belongsToMany(User::class, 'user_coupon')
->wherePivot('discount', '=', 0);
}
public function scopeAvailable(Builder $query): Builder
{
return $query->where(function ($coupons) {
return $coupons
->withCount('unused')
->where('quantity', '>', 0)
->orWhere('unused_count', '>', 0 );
});
}
I found that it related to where clause in my codes so I use having like below:
public function scopeAvailable(Builder $query): Builder
{
return $query->where(fn($coupons) => $coupons
->where('quantity', '>', 0)
->orHas('Unused')
);
}
I think the reason is that withCount / with clauses using select with groupBy under the hood which makes sense as here having vs where has described it.
I make a request like this :
Event::where('team_id', Auth::user()->currentTeam->id)
->whereHas('animals', function ($query) use ($decodedId) {
$query->where('animals.id', $decodedId)
->whereHas('health_items', function ($query) {
$query->whereColumn('date_end', 'events.end');
});
})
Thanks to whereColumn, I compare my data health_items with that of the grandparent events
$query->whereColumn('date_end', 'events.end');
It works.
Only with WhereHas, I don't have the relations data in my response (it just filters out the events)
I try to do the same by adding a with it doesn't work.
Event::where('team_id', Auth::user()->currentTeam->id)
->with(['animals' => function($query) use ($decodedId) {
$query->where('animals.id', $decodedId)
->with(['health_items' => function ($query) {
$query->whereColumn('date_end', 'events.end');
}]);
}])
Returned error : Unknown column 'events.end'
Is there a way to filter the "health_items" items using a column in the events table?
Thank you
This relationship is in my Maintenance.php
public function contactedContractor()
{
return $this->hasMany(ContactedContractor::class, 'maintenance_id');
}
I want to use the relationship in a query in my controller
$contractor_maintenances = Maintenance::whereHas('contactedContractor', function ($query) {
return $query->where('contacted_contractors.user_id', '=', 8);
})
->where('contacted_contractors.user_id', $contractor_user_id)
->latest('maintenances.created_at')
->get();
but the where clause is not working giving me this error
Unknown column 'contacted_contractors.user_id' in 'where clause
How do I use the where clause?
You've passed in the query. Maintenance doest not have user_id
->where('contacted_contractors.user_id', $contractor_user_id)
Pass your query as below.
$contractor_maintenances = Maintenance::whereHas('contactedContractor', function ($query) use ($contractor_user_id) {
return $query->where('user_id', $contractor_user_id);
})->latest('maintenances.created_at')->get();
I'm trying to add some conditional logic to my query builder but am struggling to find the right function I need to be looking in to...
Take this example;
We have model A which has many model Bs. Model B contains name and value columns. I now want to return all model As which have a model B with name 'score' and value > 50, AND another model B which has name 'group' and value 'debug'.
Without resorting to basic PHP once the models have all been returned, how would I filter by specific hasMany relationships within the query builder?
Many thanks in advance.
Using Eloquent:
Relationship: in model A:
public function b()
{
return $this->hasMany(B::class);
}
A::whereHas('b', function($b) {
$b->where(function($query) {
$query->whereName('score')
->where('value', '>', 50);
})
->orWhere(function($query) {
$query->whereName('group')
->where('value', 'debug');
});
})->get();
Using query builder:
\DB::table('a')->join('b', function ($join) {
$join->on('a.id', '=', 'b.a_id');
})->where(function ($q) {
$q->where('b.name', 'score')
->where('b.value', '>', 50);
})->orWhere(function ($q) {
$q->where('b.name', 'group')
->where('b.value', 'debug');
})
->get();
I have created many-to-many relation using belongsToMany function:
class Doctor extends Model
{
...
public function categories()
{
return $this->belongsToMany('App\Category', 'doctors_to_categories', 'doctor_id', 'category_id');
}
...
}
Now I want to create query with many-to-many condition. In SQL in would be:
SELECT *
FROM `doctors`
JOIN `doctors_to_categories`
ON `doctors_to_categories`.`doctor_id` = `doctors`.`id`
WHERE `doctors_to_categories`.`category_id` = 1
I have tried to achieve this like:
$doctors = Doctor::with(['categories' => function($query) {
$query->where('category_id', '=', 1);
}])->get();
Or
$doctors = Doctor::with(['categories' => function($query) {
$query->where('categories.id', '=', 1);
}])->get();
But it is not working. Any ideas how it should be? Thanks for any help.
The with() function does not actually introduce a join in your query, it just loads the relation of all models as a second query. So the with() function couldn't possibly change the original result set.
What you are looking for is whereHas(). This will add a WHERE EXISTS clause to the existing query.
$doctors = Doctor::with('categories')->whereHas('categories', function ($query) {
$query->where('categories.id', 1);
})->get();
Using ->with() doesn't actually limit the results of the Doctor::...->get() query; it simply tells Laravel what to return in the relationships attribute. If you actually want to enforce returning only Doctors that have a category 1 relationship, you need to use whereHas():
$doctors = Doctor::whereHas('categories', function($query) {
$query->where('categories.id', '=', 1);
// `id` or `categories.id` should work, but `categories.id` is less ambigious
})->get();
You can add whereHas condition for this. Try code below:
$doctors = Doctor::with('categories')->whereHas('categories', function($query) {
$query->where('id', 1);
})->get();