Someone can explain for me this Laravel code? - php

I have some code like below, the thing I want to ask is with the exactly same // dd($example->count()) #10 why put dd() on each different line has different value ? What change my $example event I never reassign it ?
$example = $car->wheels()->whereBetween(
'created_at',
[
$starDay->format('Y-m-d h:i:s'),
$today->format('Y-m-d h:i:s')
]
)
$total = $example->count();
// dd($example->count()) #10
$totalSuccess = $example->where('status', 'good')->count();
// dd($example->count()) # 5
$colors = $example->select('color', DB::raw('count(*) as total'))
->groupBy('color')
->get()
->toArray();
// dd($example->count()) # []

The value changes because each time you are adding more and more different clauses (like where) to your query. Those calls actually change the query object itself and the changes persist.
At first you have query object in $example with only whereBetween clause. It returns you count of 10 rows in your database.
Then you add where('status', 'good') to the query and it narrows down the selection even more down to 5 rows.
Lastly you change your $example query with select(...) and groupBy() calls.
In Laravel query builder objects are mutated when you add query constructions to it. So when you call $example->where(...) your $example query builder object will now have that where clause.

Related

How to compare a DB value to another DB value in Laravel

I want to compare two values of the database. Is it possible to do so with the "where" method? For example, the "tnx_time" would be one DB value and the "value(duration)" the other one. But I cannot now access the DB values on the 3rd field of the "where" function.
Does anybody know how to fix that?
$trnxs = Transaction::where('tnx_time', '<', date("Y-m-d", strtotime( value(duration) )) )
You can use a callback in your "where" clause to create a subquery, would be something like this (might need some changing)
$trnxs = Transaction::where('tnx_time', '<', function ($query) {
$query->selectRaw('date("Y-m-d", strtotime(value(duration)))');
})->get();

PHP Laravel - MSSQL - WhereBetween and Where

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.

Fetching a summary grouped by month with Eloquent

I have a table called gk and I am currently running two queries. Please have a look at the queries:
Gk::groupBy(DB::raw("MONTH(created_at)"))
->groupBy(DB::raw("YEAR(created_at)"))
->selectRaw('id, user_id, sum(ton) as ton,pl, count(id) as total, sum(w) , created_at')
->with(array('user'=> function($q){
$q->select('id', 'userName', 'profilePic');
}))
->where('user_id', $userData[0]->id)
->get();
This query returns a little summary of every months. As you can I see I am grouping results by months and years. And I have another query which will return all the rows of any given months.
I am running second query like this
$m=Carbon::parse($request->date);
Gk::where('user_id',$request->user_id)->whereRaw(DB::raw("YEAR(created_at)=$m->year"))->whereRaw(DB::raw("MONTH(created_at)=$m->month"))
->orderBy('created_at','desc')
->get();
The second query returns all the rows of any month. I'm executing this query in a foreach loop for all of the months that are returned in the first query.
I am trying to combine this two query into one so that I can get a group of the results by months and years and also all the details of that month.
Any help, suggestions or idea would be extremely helpful.
[Note: For the date in second query, this date is created_at result from the first query.]
Thank you.
The way I read your question is as following: The second query is executed in a loop with results from the first one. Is that right? In my answer I have explained a way to execute the second query just one time instead of in a loop. You'd still have to execute the first query once.
So, I think that you are better of using the Php collection methods:
$results = Gk::where('user_id',$request->user_id)
->orderBy('created_at','desc')
->get()
->groupBy(function (Gk $item) {
return $item->created_at->format('Y-m');
});
The groupBy method has to return an attribute on which you want to group the elements. For this example I think that using a yyyy-mm format will do fine.
Reference: https://laravel.com/docs/5.5/collections#method-groupby
Edit: Maybe you can also get rid of the orderBy method call because you are grouping by afterwards:
$results = Gk::where('user_id',$request->user_id)
->get()
->groupBy(function (Gk $item) {
return $item->created_at->format('Y-m');
});
Edit 2: To combine the information of the two queries, you could do something like the following:
$results = Gk::where('user_id',$request->user_id)
->get()
->groupBy(function (Gk $item) {
return $item->created_at->format('Y-m');
})->map(function(Collection $rows) {
return [
'sum(ton)' => $rows->sum('ton'),
'total' => $rows->count(),
'sum(w)' => $rows->sum('w'),
'rows' => $rows
];
);
Note that I have omitted a few of the selected columns in your first query because they are not unique in the given group by. But feel free to add any logic in the map function. Because we use map() after groupBy, every call of map() will receive a collection of items for one month. You can that use that fabulous collection magic to calculate all values that you need and reduce the number of queries to just one.

Assign a query to variable to then perform two separate queries?

Is it possible to start an eloquent query, assign it to a variable then continue using the variable for two separate queries without them conflicting with one another. A simple example:
$students = $this->student
// more query stuff
->where('is_active', 1);
$bachelorStudents = $students
->where('course_id', 3)
->get();
$masterStudents = $students
->where('course_id', 4)
->get();
or would I need to do:
$bachelorStudents = $this->student
->where('course_id', 3)
->get();
$masterStudents = $this->student
->where('course_id', 4)
->get();
I always thought I could do the former, but some of my results appear to show I can't but I am open to believe that if you can do it then perhaps I'm doing something wrong.
When you're calling
$students = $this->student->where('is_active', 1);
you're creating a query builder object. Calling where*() on this object updates the object by adding given criteria. Therefore it's not possible to achieve what you want in your first code snippet, because when you call
$masterStudents = $students
->where('course_id', 4)
->get();
the query builder already contains where('course_id', 3) constraint added when you bachelorStudents.
Once you do that:
$students = $this->student->where('is_active', 1);
$stundents will contain a query builder with your where clause
If you do:
$bachelorStudents = $students->where('course_id', 3)->get();
You'll add another where clasuse to the $students builder, and this should work as you expect
But, when you do:
$masterStudents = $students->where('course_id', 4)->get();
You are adding another where clasuse to the same $students builder, thus resulting the query builder to be something like this:
$students->where('is_active', 1)
->where('course_id', 3)
->where('course_id', 4)
->get();
That probably isn't what you expect, because you have 2 where clauses with different course_id values
Think of $student as an object you modify everytime you add a clause, so you can use it for progressive query building, but remember that once you've added a clause to the query builder, the object is modified and the clause will be keept in the builder, so when you re-use the builder it will contain all the clasuses you previously added
Also, Rembember that when you need to apply some pre-defined filters to your query, in Laravel you should use query scopes
While everyone is explaining query builder and how it works, here's your answer.
1) Start off your query builder
$studentsQuery = $this->student
//Start a new query builder (optional)
->newQuery()
->where('is_active', 1);
2) Clone the initial query builder to our separate queries
$bachelorStudentsQuery = clone $studentsQuery;
$masterStudentsQuery = clone $studentsQuery;
3) Assign your where conditions and get the results
$bachelorStudentsResult = $bachelorStudentsQuery->where('course_id', 3)
->get();
$masterStudentsResult = $masterStudentsQuery->where('course_id',4)
->get();
Your use case is too simple for cloning.
It might help you DRY your code when lots of method chaining has been performed, especially when applying filters to queries.

ORDER BY "the date" Laravel 5 SQL Query

I want to sort the results by the date, but this Laravel 5 SQL Query is not working as i want.
$b = DB::table('entry')
->select(DB::raw("DATE_FORMAT(created_at,'%d-%m-%Y') as tanggal"))
->groupBy(DB::raw("DATE_FORMAT(created_at,'%d-%m-%Y')"))
->orderBy(DB::raw("DATE_FORMAT(created_at,'%d-%m-%Y')"), 'asc')
->get();
Here's the easy way to achieve this
Step 1 :
Create a Model named as Entry by artisan command or manually
Step 2 :
Then from your Controller just do
$entry = Entry::orderBy('created_at', 'ASC')->get();
Then you should get the $entry array of what you need.
Hope this helps you
You can still use DB::table and simply put this orderBy. It will work just like the above mentioned.
$query = DB::table('entry')
->select(DB::raw("DATE_FORMAT(created_at,'%d-%m-%Y') as tanggal"))
->orderBy('created_at','ASC')->get(); //either this
->orderBy('updated_at','ASC')->get(); // or this
$query = DB::table('entry')
->select(DB::raw("DATE_FORMAT(created_at,'%d-%m-%Y') as tanggal"))
->orderBy('created_at','DESC')->get(); //either this
->orderBy('updated_at','DESC')->get(); // or this
Note: Either you put 'ASC' or not it will automatically sort it ascendingly.

Categories