Laravel relationships use Where - php

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();

Related

laravel: withCount return me column not found exception

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.

Laravel withPivot in subquery doesn't work in when clause

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.

Laravel eloquent, joining tables and make filter queries

I am trying to write queries to filtering tables, but it's looks like something is not right.
$keyword = "chapel";
$city = $request->get("city");
$price = $request->get("price");
First checking the plans table empty or not. Then start to write filtering queries.
$datas = Place::whereHas("plans")
->groupBy("address","place_name")
->when($keyword, function($query, $keyword) {
return $query->where("place_name", "LIKE", "%$keyword%");
})
->when($city, function($query, $city) {
return $query->where("city", "LIKE", "%$city%");
})
The queries working till basic_info table. But when I when search $keyword in basic_info table then then error pops and says
Call to undefined relationship [basic_infos] on model > [App\Model\Place].
//basic info table
->when($keyword, function($query) use ($keyword){
$query->with(["basic_infos" => function($query, $keyword){
return $query->where("basic_info.wedding_style", "LIKE", "%$keyword%");
}]);
})
//plan table
->when($price, function($query) use ($price){
$query->with(["basic_infos" => function($query, $price){
return $query->where("plans.plan_price", "<=", $price);
}]);
})
->paginate(20);
return $datas;
But actually it's defined. Here is the models
Place Model
public function basicInfos()
{
return $this->hasMany("App\Model\BasicInfo");
}
BasicInfo Model
public function place()
{
return $this->belongsTo("App\Model\Place");
}
But in query inside ->when function, when I use ->with it seems, there is a problem happening. I guess, I am using it at wrong time or else... Same thing surely will happen to plan table's query too.. What is the right way to do it?
You have two problems:
You need to use your function name instead of table name for relationship.
If you want to use another params except $query, use use.
->when($keyword, function($query) use ($keyword){
$query->with(["basicInfos" => function($query) use ($keyword){
return $query->where("wedding_style", "LIKE", "%$keyword%");
}]);
})

Laravel belongsToMany relation condition

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();

Laravel: Sort Table Joined Using 'With' Clause

I'm using Laravel 4 and Eloquent ORM. I'm currently pulling records from my database using the following code:
public function index($type, $id)
{
$asset = Asset::where('public_id', '=', $id)
->with('attachments')
->with('attachments.attachment')
->with('tracks')
->with('tracks.track')
->where('locale', '=', Config::get('app.locale'))
->first();
return View::make('view-asset.index')
->with('asset', $asset)
->with('type', $type);
}
The table joined to this query using the with('tracks') statement has a column in it called track_order - I would like to be able to sort the rows returned by this part of the query by that column so that the tracks stored in the database are returned in the correct order.
Is it possible to do this and if so, how should I do it? So far I've tried something like this:
public function index($type, $id)
{
$asset = Asset::where('public_id', '=', $id)
->with('attachments')
->with('attachments.attachment')
->with('tracks')
->with('tracks.track')
->where('locale', '=', Config::get('app.locale'))
->orderBy('tracks.track_order', 'ASC')
->first();
return View::make('view-asset.index')
->with('asset', $asset)
->with('type', $type);
}
Which doesn't work and I can't figure out a way of doing this other than splitting things up into multiple queries.
You most certainly can:
with(['tracks' => function($query)
{
$query->orderBy('track_order', 'asc');
}])
Refer to Eager Loading Contraints in the documentation for more.

Categories