How to find value within a range - laravel - php

I have two columns in a table like below
id start end point
1 50 70 5
2 80 100 7
How can find the value's range in my code below.. Now when i submit the mark (70), i want to find the range it belongs to so i can get the respective points.
lets say $marks = 70
public function getGrade($marks)
{
$grade_point = Grade::where(function ($query) use ($marks) {
$query->where('from', '<=', $marks);
$query->where('to', '>=', $marks);
return $grade_point->point;
}
With the code above i get the error
Object of class Illuminate\Database\Eloquent\Builder could not be converted to string

You need to send the query with a method like get(), first(), pluck('column'), value('column')....
lets say $marks = 70
public function getGrade($marks)
{
$grade_point = Grade::where('from', '<=', $marks)->where('to', '>=', $marks);
return (int)$grade_point->value('point');
}
the method value('column') returns the column's value of the firsts result or null.

You have to call ->first(), ->get() or ->all() to execute to the query:
// lets say $marks = 70
public function getGrade($marks)
{
$grade_point = Grade::where(function ($query) use ($marks) {
$query->where('from', '<=', $marks);
$query->where('to', '>=', $marks);
})->first();
return $grade_point->point;
}
Checkout the docs: https://laravel.com/docs/5.8/queries#retrieving-results

Related

Eloquent: has() condition against database value

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

Take last 3 records from child. Php/Laravel

Help me please.
I'm trying to write a function where I get all the categories of my forum with the 3 most recently updated Topics in the given categories.
But according to the result, take(3) filters by id (where the id is not higher than 3), and I need to get the last 3 records.
public function index()
{
$forums = Category::with(['posts' => function ($q){
return $q->take(3)->get();
}])->get();
dd($forums);
}
you should order your complete query by update_at descending, only after you can take the first 3.
$q->orderBy('update_at', 'desc')->take(3)->get();
Your Categories table seems to be a different table from posts, so when a post is created or updated you should also set update_at of its category to now.
As far as I know you can not use take() or limit() inside with();
EDIT: solution that was selected by mr.Sardov is to use package staudenmeir/eloquent-eager-limit.
Link is provided below this answer.
So for you need to do is by limit it from model relationship.
For example:
class Category extends Model {
public function posts()
{
return $this->hasMany('App\Models\Post');
}
public function limitPosts()
{
return $this->hasMany('App\Models\Post')
->limit(3);
}
public function limitLatestPosts()
{
return $this->hasMany('App\Models\Post')
->orderBy('created_at', 'desc'). // or use ->latest()
->limit(3);
}
}
And that use it like this:
Category::query()
->with(['limitPosts' => function($query) {
$query->orderBy('created_at', 'desc'); // the last records
}])
->where('id', '<=', 3) // id not higher than 3
->get();
Or
Category::query()
->with('limitLatestPosts')
->where('id', '<=', 3) // id not higher than 3
->get();
Hope this can help you out.

laravel eloquent complex select inside where statement

halo, i have data and want to display it like picture below
there are two models relationship, Person and Installment.
this is Person model:
class Person extends Model
{
protected $table = 'person';
public function angsuran()
{
return $this->hasMany(Installment::class);
}
}
this is Installment model:
class Installment extends Model
{
protected $table = 'installment';
public function person()
{
return $this->belongsTo(Person::class);
}
}
and this is my controller to querying and display data
$data = Person::with('angsuran')
->whereHas('angsuran', function ($q) {
$q->whereBetween('installment_date', [\DB::raw('CURDATE()'), \DB::raw('CURDATE() + INTERVAL 7 DAY')])
->where('installment_date', '=', function () use ($q) {
$q->select('installment_date')
->where('status', 'UNPAID')
->orderBy('installment_date', 'ASC')
->first();
});
});
return $data->get();
it show error unknow colum person.id in where clause
please help. thanks.
As the comment said, you need to put $q as a parameter to the Closure.
When using subqueries, it's useful to tell the query builder which table it is supposed to query from.
I've rewritten your query. It should achieve what you're looking for. Also, changed the CURDATE to Carbon objects.
today() returns a datetime to today at 00:00:00 hours. If you need the hours, minutes and seconds, replace today() by now().
$data = Person::with('angsuran')
->whereHas('angsuran', function ($subquery1) {
$subquery1->where('installment_date', function ($subquery2) {
$subquery2->from('installment')
->select('created_at')
->where('status', 'UNPAID')
->whereBetween('installment_date', [today(), today()->addWeeks(1)])
->orderBy('installment_date')
->limit(1);
});
});
Using with and whereHas you will end up with two query even if you have limit(1) in your subQuery and the result will show all 4 installment related to the person model. also I don't think you can order on the subquery, it should be before the ->get
so here's i've rewritten your code
$callback = function($query) {
$query->whereBetween('installment_date', [today(), today()->addDays(7)])
->where('status', 'UNPAID')
->orderBy('installment_date');
};
$data = Person::whereHas('angsuran', $callback)->with(['angsuran' => $callback])->get();
or you can use query scope. please see this answer Merge 'with' and 'whereHas' in Laravel 5

Laravel Eloquent - How Can I Sum fields inside relation's column?

I need to sum every paid_amount inside of each expense_payment_liab instead of returning all these
individual paid_amount as it can be seen in images for clear view.So far my query looks like this:
Model Relation is like Voucher has many Expenses and Expenses has many Expensepaymentliab.
This is so far what I tried:
$expense = Voucher::where('voucher_date', $request->date)
->where('account_id', 1)
->with(['expenses' => function ($expense) use ($date) {
$expense->with(['expPaymentLiab' => function ($inner) use ($date) {
return $inner->select('paid_amount', 'expense_id')->where('paid_date', '=', $date);
//need to return the sum of paid_amount.
// I've also tried this
//$inner->sum('paid_amount')
// $inner->sum('paid_amount', 'expense_id')
}]);
$expense->select('id', 'date', 'total_amount', 'voucher_id');
}])->get();
These are the images please check
Need to sum such paid_amount field.
You can use withCount to sum the paid_amount field.
Voucher::where('voucher_date', $request->date)
->where('account_id', 1)
->with(['expenses' => function ($expense) use ($date) {
// select the columns first, so the subquery column can be added later.
$expense->select('id', 'date', 'total_amount', 'voucher_id');
$expense->withCount(['expPaymentLiab AS paid_sum' => function ($query) use ($date) {
return $query->select(DB::raw('SUM(paid_amount)'))->where('paid_date', '=', $date);
}]);
}])
->get();

Laravel Multiple requirements for relationship

I have an Item table, Meta table and a Item_Meta table which has all meta records for Items. One Item has many Meta records.
Item_meta has the following columns:
Item_id | Meta_id | Value
Lets say I have a requirements:
Requirement 1 - ['Meta_id' => 1, 'value' => 'new']
Requirement 2 - ['Meta_id' => 3, 'value' => 'LCD']
I need to build a query get all items, which have meta_id with id 1 equal to new, and meta_id with id 3 equal to LCD.
So if an item does not have one of this metas (or one of metas has wrong value) it should not be returned.
You can filter your models on relation's attributes using Eloquent's whereHas() method. In your case the following code should do the trick:
$items = Item::whereHas('metas', function($query) {
$query->where('Meta_id', 1);
$query->where('value', 'new);
})
->whereHas('metas', function($query) {
$query->where('Meta_id', 3);
$query->where('value', 'LCD);
})
->get();
I assumed that your item->meta relation is called metas.
You could also use another form of using whereHas() where you provide number of matching related records. The code will be a bit more complex but it will result in less subselects in the executed query:
$items = Item::whereHas('metas', function($query) {
$query->where('Meta_id', 1);
$query->where('value', 'new);
$query->orWhere(function($query2) {
$query2->where('Meta_id', 3);
$query2->where('value', 'LCD);
};
}, '=', 2)
->get();
I have tried the first approach from the previous answer before asking the question, but it failed so I thought it had a mistake. But after seeing and that answer it seemed that I don't understand something. So I digged inside of Laravel Eloquent internals and here is what I found:
Eloquent Build class "::where" method changes $this->query property before returning the instance. Here is the code:
public function where($column, $operator = null, $value = null, $boolean = 'and')
{
if ($column instanceof Closure) {
$query = $this->model->newQueryWithoutScopes();
call_user_func($column, $query);
$this->query->addNestedWhereQuery($query->getQuery(), $boolean);
} else {
call_user_func_array([$this->query, 'where'], func_get_args());
}
return $this;
}
Take notice of "$this->query->addNestedWhereQuery($query->getQuery(), $boolean);" on the 6th line.
The Builder class "::whereHas" method does not modify "$this->query" property.
public function whereHas($relation, Closure $callback, $operator = '>=', $count = 1)
{
return $this->has($relation, $operator, $count, 'and', $callback);
}
So, what it has to do with my problem. I have created a query like this:
$query = Item::where('active',1);
Then I added the conditions:
if($meta){
$query->whereHas('metas', function($query) {
$query->where('Meta_id', 1);
$query->where('value', 'new);
})
->whereHas('metas', function($query) {
$query->where('Meta_id', 3);
$query->where('value', 'LCD);
})
}
and then query was performed:
$query->get();
The mistake was related to ::whereHas method, what I had to do was assign whereHas result to the variable:
if($meta){
$query = $query->whereHas('metas', function($query) {
$query->where('Meta_id', 1);
$query->where('value', 'new);
})
->whereHas('metas', function($query) {
$query->where('Meta_id', 3);
$query->where('value', 'LCD);
})
}
So thats all. Always check with internals if something works unexpectadely

Categories