Eloquent: has() condition against database value - php

I have a simple relationship between Bottles and InventoryItems:
InventoryItem.php:
public function bottles(): HasMany
{
return $this->hasMany(InventoryItemBottle::class);
}
I'm trying to query for InventoryItem's that have a bottles count of greater then a user entered threshold.
The user's input is saved in a JSONB. Part of the query looks like this and I've commented the problem line:
->when(
$filters['filter'] === 'show_above_max_threshold',
fn (Builder $query): Builder => $query->where(function (Builder $query): Builder {
return $query->whereColumn('info->quantity', '>', 'info->high_level_warning');
})
->orWhere(function (Builder $query): Builder {
return $query->has('bottles', '>', 'info->high_level_warning'); // stuck here
})
)
The has() method should help here, but how do I get the high_level_warning from the database to pass to it? Or is there another method I could use?

You can use the has function.
See if this helps you.
$threshold = 2;
$items = InventoryItem::has('bottles', '>=', $threshold)->get();

Related

How to get eloquent data which was created before mode itself

I have two tables (products and product_bids). While getting product_bids i need to attach the products which were created before the bid itself.
Here's my code:
$query = ProductBid::whereStatus(ProductBid::STATUS_ACTIVE)->whereNot('user_id', Auth::id());
$query->whereHas('product', function ($q) {
$q->whereIn('code', Product::whereUserId(Auth::id())->select('code')->get())
->whereStatus(Product::STATUS_ACTIVE);
});`
In this case how can I write a condition to take the products which were created before the product_bid. (products.created_at < product_bids.created_at). I can't find a way to write this in query builder.
$query = ProductBid::whereStatus(ProductBid::STATUS_ACTIVE)
->whereNot('user_id', Auth::id())
->whereHas('product', static function (Builder $q): void {
$q->whereColumn('products.created_at', '<', 'product_bids.created_at')
->whereIn('code', Product::whereUserId(Auth::id())->pluck('code'))
->whereStatus(Product::STATUS_ACTIVE);
})->get();

Laravel get a query to check if at least one of two relationships exist with QueryBuilder without ignoring other filters

I have a model Affiliate that has a relationship hasMany() with Activities and Transfers
Im filtering my affiliates now and want to retrieve the affiliates that have at leat 1 activity OR at least one transfer (it can have 0 activities and 1 transfer and will pass). Also I must ignore a given array of invalid affiliate's ids
this is what I tried
$affiliates = Affiliate::whereNotIn('id',$invalidIds);
if ($params['sales']){
$affiliates = $affiliates->whereHas('activities', static function (Builder $builder) use ($params) {
$builder->where('status','>',0)
->where('status','<',8)
;
})->orWhereHas('transfers', static function (Builder $builder) use ($params) {
$builder->where('status','>',0)
->where('status','<',8)
;
});
}
$affiliates = $affiliates->get();
using the whereHas and orWhereHas should work but the problem I believe is that in the orWhereHas() it currently ignores the other filters (in this case the filter that ignores the $invalidIds for affiliates) so I get the affiliates that at least have one activity or one transfer but I don't ignore the invalid ids
am I doing something wrong? or there is a different way to approach this problem?
Try this:
$affiliates = Affiliate::whereNotIn('id',$invalidIds);
if ($params['sales']){
$affiliates = $affiliates->where(function($query){
$query->whereHas('activities', function ($q1){
$q1->where('status','>',0)->where('status','<',8);
})
->orWhereHas('transfers',function ($q2){
$q1->where('status','>',0)->where('status','<',8);
});
});
}
$affiliates = $affiliates->get();
I'm not entirely sure but I think playing around with method order will work.
$affiliates = Affiliate::query();
if ($params['sales']) {
$affiliates = $affiliates->whereHas('activities', static function (Builder $builder) use ($params) {
$builder->where('status', '>', 0)
->where('status', '<', 8);
})->orWhereHas('transfers', static function (Builder $builder) use ($params) {
$builder->where('status', '>', 0)
->where('status', '<', 8);
});
}
$affiliates = $affiliates->whereNotIn('id', $invalidIds)->get();

Can not use where clause after using with clause in Laravel query

I am writing a query using with and then where clause in laravel.
$users = User::query()->with('roles')->where('name', '!=', 'customer')->get();
return $users;
But where clause is not working here. Customers are not excluded. I am providing the snap shot of the query result.
I think you need whereHas() :
use Illuminate\Database\Eloquent\Builder;
$users = User::query()
->with('roles')
->whereHas('roles', function (Builder $query) {
$query->where('name', '!=', 'customer');
})
->get();
return $users;
I suppose you trying to filter relation data in base query.
Try smth like that:
$users = User::query()->with([
'roles' => function ($q) {
$q->where('name', '!=', 'customer');
}])
->get();
return $users;
Doc

Laravel Eloquent Query Where nested relationship

I am new to laravel and i am trying to write a query whereby the selected stock->OrderProduct->product_id is passed to get the relevant result. The query looks like this :
$stock = Stock::where('orderProductid.product_id', $pharmacyEvent->prescription->product_id)
->whereHas('orderProduct.product.prices')
->with(['orderProduct.product.price' => function ($query) use ($paymentMode) {
$query->where('scheme_id', $paymentMode->scheme_id);
}])->first();
$price = $stock->orderProduct->product->price;
This doesnt work as it is bad practise and i rewrote the query like below, which brings me wrong results.
$stock = Stock::whereHas('orderProduct.product.prices')
->with([
'orderProduct.product' => function ($query) {
$query->where('id', $pharmacyEvent->prescription->product_id);
},
'orderProduct.product.price' => function($query) {
$query->where('scheme_id', $paymentMode->scheme_id);
}
])->first();
Any advise on eloquent methods to use when i want to pass a condition based on relationships in a query will be highly appreciated. I am using lavel 5.8
I used whereHas :
$stock = Stock::whereHas('orderProduct.product', function($query) use ($pharmacyEvent) {
$query->where('id', $pharmacyEvent->prescription->product_id);
})
// ->whereHas('orderProduct.product.prices')
->with(['orderProduct.product.price' => function ($query) use ($paymentMode) {
$query->where('scheme_id', $paymentMode->scheme_id);
}])->first();
$price = $stock->orderProduct->product->price;

Laravel Check Value For One Specific Record In hasMany Relationship Within Query Builder

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

Categories