How do I use one query builder to fetch results twice? With Carbon I have use CarbonImmutable to achieve this but with eloquent, one fetch is affecting the others down the line.
Here is the code.
$expenses = PropertyExpense::with(['bill'])
->where('contractor_id', $supplier);
/* I run this to get balance brought forward */
$oldDebits = $expenses->whereDate('txn_date', '<', $start)
->sum('billed'); //here I get actual bbf value.
/* Then I run this to get the debits for the start and end period */
$debits = $expenses
->whereDate('txn_date', '>=', $start)
->whereDate('txn_date', '<=', $end)
->get(); //Here I get empty array. Which should not be the case.
When I remove the $oldDebits Section, I get the Collection of all debits as expected.
I have even rewritten the code to temporarily assign expenses to another variable before executing the sum to no avail. Here.
$olderDebits = $expenses;
$oldDebits = $olderDebits->whereDate('txn_date', '<', $start)->sum('billed');
When I ran this, am still getting the same results: correct $oldDebits and an empty collection for $debits.
Any assistance?
Am using Laravel V9 and PHP 8.1.
That is because you ->whereDate() on to the same variable which is $expenses.
In your case, you should clone the query builder before execute it.
Such as
$expenses = PropertyExpense::with(['bill'])->where('contractor_id', $supplier);
$oldDebits = (clone $expenses)->whereDate('txn_date', '<', $start)->sum('billed');
$debits = (clone $expenses)
->whereDate('txn_date', '>=', $start)
->whereDate('txn_date', '<=', $end)
->get();
Related
I am trying to select records from my MSSQL database, with below parameters:
Column 'first_etd' must be between two dates
Column 'car_id' must not be the same as the current $carId variable.
This is my code:
$carId = 47;
$from = Carbon::now()->subWeeks(2)->startOfWeek()->toDateString();
$to = Carbon::now()->addWeeks(4)->endOfWeek()->toDateString();
$consols = Consol::with(['car'])
->where('car_id', '!=', $carId)
->whereBetween('first_etd', [$from, $to])->get();
The above variable $consols returns no results.
If I remove the ->where('car_id', '!=', $carId) from the statement, I successfully get results.
All the records in my database currently have NULL in the car_id column:
I have also tried to change the != operator to <> without any luck.
So this is not a fix to the SQL statement itself, but more a fix to my problem.
As said in my OP, I can find the two records if I remove the where() method. I figured I could start by getting the records, that's between my two dates and then do the where() filtering on the result collection.
This works:
//Get the records from the database, that's between two dates.
$consols = Consol::with(['car'])->whereBetween('first_etd', [$from, $to])->get();
//Now $consols is a Laravel collection, so I can use the where() method here.
$consols = $this->consols->where('car_id', '!=', $carId);
Above successfully returns the two records.
I have one table named as Package. Currently, I want to filter the table actually. Let say the user insert values into variable, for example, from = 2/3/2020 and to = 10/3/2020. Then it will be calculated inside my coding and get the duration of days, resulting noOfdays = 8 days. So, from the duration, it will determined, which packages it belongs within the duration of 8 days.
calculation of days :
$today = Carbon::now();
$dt1 = Carbon::createFromFormat('d/m/Y',$departure);
$dt2 = Carbon::createFromFormat('d/m/Y',$arrival);
$noOfDays = $dt1->diffInDays($dt2);
The calculation have no error, which when dd($noOfDays), it will result = 8 days.
SQL statement :
$packages = Package::where([
['id', '=', $plan],
['from', '<=', $noOfDays, 'AND', 'to', '>=', $noOfDays],
])
->get();
Package Table :
The error part is, when I filtering, it will get Package 1 and package 2. It supposed to get only the package 2. I think it have something wrong somewhere around the SQL statement. Anyone whoever in this situation before? because logically I think, the SQL part is true already. But it why it filter and get the package 1?
You have to separate your two where clause to get what you wanted like this.
$packages = Package::where([
['id', '=', $plan],
['from', '<=', $noOfDays],
['to', '>=', $noOfDays]
])
->get();
To be more readable, its good if your code goes like this
$packages = Package::where('id', $plan)
->where('from', '<=', $noOfDays)
->where('to', '>=', $noOfDays)
->get();
Change your second where statement. Where clause is always using an ADN unlelss you use orWhere or nest it in a function.
['id', '=', $plan],
['from', '<=', $noOfDays],
['to', '>=', $noOfDays]
The 4th parameter, that you are passing as an AND is not used like you are expecting it to work.
Which results to package1 to be included in your output.
I am trying to get only the current dates and the previous dates.Here is how i tried
$jobseekers = Calllog::orderBy('calllogs.created_at','DESC')
->get()->where('call_back_date', '<=', Carbon::today()->toDateString());
This show only the previous dates, i want to get both.If i remove "<", it shows only the current date.Help me out please.
Use tomorrow and < condition
$jobseekers = Calllog::orderBy('calllogs.created_at','DESC')
->get()->where('call_back_date', '<', Carbon::tomorrow()->toDateString());
use below eloquent query
$jobseekers = Calllog::whereDate('call_back_date','<=',Carbon::today)->get()
$jobseekers = Calllog::orderBy('calllogs.created_at','DESC')->where('call_back_date', '<=', Carbon::now())->get();
Using now() instead of today(). Unlike today(), now() returns complete datetime at the moment.
Also notice that i moved where condition before get() to prevent fetching extra data from database.
I'm having a lot of trouble figuring out how to use this collection to count rows.
$wordlist = \DB::table('wordlist')->where('id', '<=', $correctedComparisons)
->get();
I have tried adding->count() but didn't work. I have tried doing count($wordlist). I'm not really sure what to do without needing a second request as a->count() method.
Answer has been updated
count is a Collection method. The query builder returns an array. So in order to get the count, you would just count it like you normally would with an array:
$wordCount = count($wordlist);
If you have a wordlist model, then you can use Eloquent to get a Collection and then use the Collection's count method. Example:
$wordlist = Wordlist::where('id', '<=', $correctedComparisons)->get();
$wordCount = $wordlist->count();
There is/was a discussion on having the query builder return a collection here: https://github.com/laravel/framework/issues/10478
However as of now, the query builder always returns an array.
Edit: As linked above, the query builder now returns a collection (not an array). As a result, what JP Foster was trying to do initially will work:
$wordlist = \DB::table('wordlist')->where('id', '<=', $correctedComparisons)
->get();
$wordCount = $wordlist->count();
However, as indicated by Leon in the comments, if all you want is the count, then querying for it directly is much faster than fetching an entire collection and then getting the count. In other words, you can do this:
// Query builder
$wordCount = \DB::table('wordlist')->where('id', '<=', $correctedComparisons)
->count();
// Eloquent
$wordCount = Wordlist::where('id', '<=', $correctedComparisons)->count();
Direct get a count of row
Using Eloquent
//Useing Eloquent
$count = Model::count();
//example
$count1 = Wordlist::count();
Using query builder
//Using query builder
$count = \DB::table('table_name')->count();
//example
$count2 = \DB::table('wordlist')->where('id', '<=', $correctedComparisons)->count();
Its better to access the count with the laravels count method
$count = Model::where('status','=','1')->count();
or
$count = Model::count();
also, you can fetch all data and count in the blade file.
for example:
your code in the controller
$posts = Post::all();
return view('post', compact('posts'));
your code in the blade file.
{{ $posts->count() }}
finally, you can see the total of your posts.
//controller $count = Post::count(); return view('post', compact('count'));
//blade {{$count}}
or
//controller $posts = Post::all(); return view('post', compact('posts'));
//blade{{count($posts)}}
I'm running this code on Laravel. I'm adding filters/ordering if I receive them and I'm altering the query before running it and then paginate the results.
$aDatas = DB::table('datas');
if (!empty($aLocations)) {
foreach ($aLocations as $oLocation) {
$aDatas->orWhere('pc', '=', $oLocation->pc);
}
}
if (!empty($oFilters->note)) {
$aDatas->where('note', '>=', $oFilters->note);
}
if (!empty($oFilters->nb_comments)) {
$aDatas->where('nb_comments', '>=', $oFilters->nb_comments);
}
if (!empty($oOrder->type)) {
$aDatas->orderBy($oOrder->type, $oOrder->sort);
}
// echo $aDatas->where('note', '>=', 5)->count() ????
It's working fine.
But I'd like to use these results to count several parts of it.
The last line shows what I tried to do, counting how many rows in these filtered results have a note >= 5. But doing this will actually filter my original data.
I thought about assigning $aDatas to another variable and then count on this, but I'll have many counts and that seems dirty.
Is there a sweet way to do this ?
Just save your datas an replace the last line with this:
$datas =$aDatas->where('note', '>=', 5)->get();
echo $datas->count();
//use datas here for more action.
For all of your requirement, you might want to resolve in making several queries because a single query will not be able to do that(based from what I know)
//this is to get your total of note greater than 5
$query = DB::table('datas');
$query->where('note', '>=', 5);
$data = $query->paginate(10);
$count = $data->getTotal();
to get your other data
If you are working with pagination, use getTotal() instead
$query = DB::table('datas');
$query->select(
DB::raw('COUNT(stars) AS count'),
DB::raw('starts'),
);
$query->where('notes', '>=', 5);
$query->groupBy('stars');
$data = $query->get();