Laravel 4 array to string conversion - laravel

I tried to ran a query, but it returns an Array to string conversion error. I can't fix it, I tried several things, but didn't locate the error.
<td>{{ DB::select( DB::raw('SELECT * FROM `player_deaths` WHERE `player_id`='.$s->id.' order by `time` DESC LIMIT 0, 10') ); }}</td>

You can write your query in a neater way, like that:
DB::table('player_deaths')->where('player_id', '=', $s->id)->orderBy('time', 'desc')->skip(0)->take(10)->get()->toArray();
And you get the error because you want to print out an array. Instead you should iterate over it in a foreach loop.
#foreach (DB::table('player_deaths')->where('player_id', '=', $s->id)->orderBy('time', 'desc')->skip(0)->take(10)->get() as $death)
<td> {{ $death }} </td>
#endforeach
In general, what are you trying to do here ?
Traditionally, Read The Manual man ... it's all there.
http://four.laravel.com/docs/queries
http://four.laravel.com/docs/templates#blade-templating

Related

Laravel displays field as 0 although theres a value returned

So the dd of a query is shown below
Whenever I try to get the value of totalsales, I get 0. My query:
$this->query = Sales::with(['item', 'branch'])->isSales()->groupBy('item_id')
->select(DB::raw('count(*) as total, SUM(costs) as costs,SUM(profit) as profits, SUM(selling_price) as totalsales,item_id'))->orderBy('total','DESC');
$this->query = $this->query->whereBetween('date',[$this->start_date,$this->end_date]);
$qq = $this->query;
$sales = $this->query->paginate($this->perPage);
and I output the value in a table cell in blade as follows:
<td>
{{ number_format($sale->totalsales, 3) }}
</td>
Note: all other attributes are displaying correctly
Thank you

How to access prev or next array at foreach blade laravel

I currently develop a blade View that will loop an array from Controller.
I just create a table that have an aspects, detail aspects, current status, and remark. So, I want loop (with foreach) at my blade view, then at my array there will be a condition that aspects have same value in next row.
For table example:
Aspects | Detail Aspects | Current Status | Remark
Curriculum | 1 | Good | Good
Curriculum | 2 | Good | Good
Curriculum | 3 | Good | Good
Teaching | 4 | Good | Good
So for the table, I want to check if prev.Aspect == current.Aspect, so I don't need to print it again, or maybe I can rowspan that .
I already using $index at my foreach, but I only can print it as number, not accessing my Obj[index] value.
Here my blade code :
<table border='1'>
<tr align='center' class='header'><td>Aspects</td><td>Details</td><td>Current Status</td><td>Remark</td></tr>
#foreach($prAspect as $index => $data)
<tr>
<td>{{$data->praDesc}}</td>
<td>{{$data->prsDesc}}</td>
<td>{{$data->currentStatus}}</td>
<td>{{$data->remark}}</td>
</tr>
#endforeach
</table>
You could use for loop instead :
#for ($i = 0; $i < count($prAspect); $i++)
// use $i as index
// use $prAspect[$i]
#endfor
Add ->toArray() to your query builder when you fetch the data. This will help your purpose in this case to access the items as an array for easier comparison.
<table border='1'>
<tr align='center' class='header'><td>Aspects</td><td>Details</td><td>Current Status</td><td>Remark</td></tr>
#foreach($prAspect as $index => $data)
<tr>
<td>{{$data['praDesc']}}</td>
<td>{{$data['prsDesc']}}</td>
<td>{{$data['currentStatus']}}</td>
<td>{{$data['remark']}}</td>
</tr>
#endforeach
</table>
Try it might help
#foreach($prAspect as $index => $data)
<tr>
<td>{{!$loop->first ? $prAspect[$index- 1]->praDesc : $data->praDesc}}</td>
<td>{{!$loop->first ? $prAspect[$index - 1]->prsDesc : $data->prsDesc }}</td>
<td>{{!$loop->first ? $prAspect[$index- 1]->currentStatus : $data->currentStatus }}</td>
<td>{{!$loop->first ? $prAspect[$index- 1]->remark : $data->remark }}</td>
</tr>
#endforeach

Laravel query builder strange result with join

I have a query
$orders = DB::table('orders')->where('user_id', $user->id)->get();
And this is what I have in view:
#foreach ($orders as $order)
{{ $order->id }}
#endforeach
It prints out 1 2 3, because the table has these three IDs.
But if I try to join, I get a rather unpredicted result.
$orders = DB::table('orders')->where('user_id', $user->id)->
leftJoin('status', 'orders.status_id', '=', 'status.id')
->get();
It gives 2 1 1. Result is the same with rightJoin() and join().
I thought this command would append row from status table to every corresponding row of orders table. Join on orders.status_id = status.id.
Can I get an intended result?
I have tried ->select('orders.*') but it did not change the result.
But still, I needed to alias everything out, as suggested in the comments here. So here is my final query.
$orders = User::find($user->id)->orders()->
select('orders.id as order_id', 'status.id as status_id',
'status.label as label', 'orders.ordered_at as ordered_at')
->leftJoin('status', 'orders.status_id', '=', 'status.id')
->get();
Probably this could be done in more pretty way, but this works.
Thank you who commented the post.
UPD: Now, I have fixed relations between my models and I can do this much simpler. As described here Laravel Many-to-one relationship
$orders = Order::with('status')->where('user_id', '=', $user->id)->get();

Group collection by date in Laravel

I am trying to group my results by date. My date field is a mySQL timestamp and I am using Laravel 4.1. For the purpose of this, I am using a field named 'start_time' and need it to group literally by date only, disregarding the actual time.
Can anyone point me in the right direction? I am unfamiliar with using dates like this in this framework.
$agenda = Agenda::where('active', '=', 'Y');
$agenda->with('user');
$agenda->with('room');
$agenda->groupBy(DB::raw('DATE_FORMAT(start_time, "%d/%m/%Y")'));
$agenda->orderBy('start_time', 'asc');
$agenda->distinct();
$agenda->get();
return View::make('agenda')->with('agendas', $agenda);
#foreach($agendas as $agenda)
{{ date("d M Y",strtotime($agenda->start_time)) }}
#endforeach
This may be a very basic approach but that's how I always do it:
<?php $currentDate = null ?>
#foreach($agendas as $agenda)
<?php $date = date("d M Y",strtotime($agenda->start_time)); ?>
#if($currentDate != $date)
<?php $currentDate = $date; ?>
<h3>{{ $date }}</h3>
#endif
{{-- do the stuff --}}
#endforeach
It would be nice (and best/better practice) not to do the date formatting like this in the view. But you get the idea.
May be you would split to more foreach loop (?) .
At first, we will query to get all of start_time with distinct, order, eta...
Then, push a foreach loop to get data belonged to each start_time element.
Hope this will be usefull.

Laravel Eloquent groupBy() AND also return count of each group

I have a table that contains, amongst other columns, a column of browser versions. And I simply want to know from the record-set, how many of each type of browser there are. So, I need to end up with something like this: Total Records: 10; Internet Explorer 8: 2; Chrome 25: 4; Firefox 20: 4. (All adding up to 10)
Here's my two pence:
$user_info = Usermeta::groupBy('browser')->get();
Of course that just contains the 3 browsers and not the number of each. How can I do this?
This is working for me:
$user_info = DB::table('usermetas')
->select('browser', DB::raw('count(*) as total'))
->groupBy('browser')
->get();
This works for me (Laravel 5.1):
$user_info = Usermeta::groupBy('browser')->select('browser', DB::raw('count(*) as total'))->get();
Thanks Antonio,
I've just added the lists command at the end so it will only return one array with key and count:
Laravel 4
$user_info = DB::table('usermetas')
->select('browser', DB::raw('count(*) as total'))
->groupBy('browser')
->lists('total','browser');
Laravel 5.1
$user_info = DB::table('usermetas')
->select('browser', DB::raw('count(*) as total'))
->groupBy('browser')
->lists('total','browser')->all();
Laravel 5.2+
$user_info = DB::table('usermetas')
->select('browser', DB::raw('count(*) as total'))
->groupBy('browser')
->pluck('total','browser');
If you want to get collection, groupBy and count:
$collection = ModelName::groupBy('group_id')
->selectRaw('count(*) as total, group_id')
->get();
Cheers!
Open config/database.php
Find strict key inside mysql connection settings
Set the value to false
Works that way as well, a bit more tidy.
getQuery() just returns the underlying builder, which already contains the table reference.
$browser_total_raw = DB::raw('count(*) as total');
$user_info = Usermeta::getQuery()
->select('browser', $browser_total_raw)
->groupBy('browser')
->pluck('total','browser');
Try with this
->groupBy('state_id','locality')
->havingRaw('count > 1 ')
->having('items.name','LIKE',"%$keyword%")
->orHavingRaw('brand LIKE ?',array("%$keyword%"))
$post = Post::select(DB::raw('count(*) as user_count, category_id'))
->groupBy('category_id')
->get();
This is an example which results count of post by category.
Laravel Version 8
Removed the dependency of DB
$counts = Model::whereIn('agent_id', $agents)
->orderBy('total', 'asc')
->selectRaw('agent_id, count(*) as total')
->groupBy('agent_id')
->pluck('total','agent_id')->all();
Another way would be this:
$data = Usermeta::orderBy('browser')->selectRaw('browser, count(*) as total')->get()
Since this is the top result when i search for eloquent count with groupby returns only first
using "illuminate/database": "^9.38" in composer. so "should" be the latest at the time of this post
I honestly have no idea why they think that returning the first record is the right option.. ie
IMHO the current implementation doesn't make sense for queries including groupBy statements.
Why should be N_1 be the "right" result?
Since #taylorotwell rightly pointed out some performance issues with counting the subquery results, why don't we fix that on the php side, by checking if there are any group statements, and if so, performing a N_1 + N_2 + .... + N_M ?
https://github.com/laravel/ideas/issues/1693#issuecomment-621167890
Wrapping the query and doing a count seems to work for me
$records = ...
$record_count = DB::table( "fake" );
$record_count->fromSub($records->select(DB::raw(1)),"query");
$record_count->count();
create a "fake" query builder
add a sub "from" from (...) query set the "sub query" to select 1 instead of returning huge column data. not sure if this is needed but in my mind it seems like a good idea
do the normal ->count()
returns the "expected" result since it executes:
select count(*) as aggregate from (select 1 from ... group by ...) as `query`
The sub is the "query" that $records would normaly execute
My use-case is for pagination (not using laravel). so i get the record count then pass it to the paginator then call ->forPage()->get()
https://github.com/laravel/framework/issues/44081#issuecomment-1301816710
Laravel Eloquent query that uses the GROUP BY clause with advanced aggregation functions and conditional statements.
GroupBy on one column.
$data = Employee::select(
'department',
DB::raw('SUM(salary) as total_salary'),
DB::raw('COUNT(*) as total_employees'),
DB::raw('SUM(IF(bonus > 13000, 1, 0)) as employees_with_bonus')
)
->groupBy('department')
->havingRaw('total_employees > 5 AND total_salary > 10000')
->orHavingRaw('department_rank LIKE ?', array("%$keyword%"))
->get();
In the above query, if the bonus is greater than 13000, the IF function returns 1 otherwise it returns 0.
GroupBy on two columns: The groupBy method takes multiple arguments
$data = Employee::select(
'department',
'location',
DB::raw('SUM(salary) as total_salary'),
DB::raw('COUNT(*) as total_employees'),
DB::raw('SUM(IF(bonus > 1000, 1, 0)) as employees_with_bonus')
)
->groupBy('department', 'location')
->havingRaw('total_employees > 5 AND total_salary > 10000')
->get();
GroupBy and JOIN: Laravel Eloquent query that joins two tables and uses grouping and aggregate functions. (inner join)
$data = Employee::select(
'employees.department',
'employees.location',
DB::raw('SUM(employees.salary) as total_salary'),
DB::raw('COUNT(*) as total_employees'),
DB::raw('SUM(IF(employees.bonus > 1000, 1, 0)) as employees_with_bonus')
)
->join('departments', 'employees.department', '=', 'departments.name')
->groupBy('employees.department', 'employees.location')
->havingRaw('total_employees > 5 AND total_salary > 10000')
->get();
Raw MySQL Query:
SELECT
department,
SUM(salary) AS total_salary,
COUNT(*) AS total_employees,
SUM(IF(bonus > 1000, 1, 0)) AS employees_with_bonus
FROM
employees
GROUP BY
department
HAVING
total_employees > 5 AND total_salary > 13000;
If you want to get sorted data use this also
$category_id = Post::orderBy('count', 'desc')
->select(DB::raw('category_id,count(*) as count'))
->groupBy('category_id')
->get();
In Laravel 8 you can use countBy() to get the total count of a group.
Check the documentation on the same.
https://laravel.com/docs/8.x/collections#method-countBy
Simple solution(tested with Laravel 9 and Spatie/Permissions).
Controller:
//Get permissions group by guard name(3 in my case: web, admin and api)
$permissions = Permission::get()->groupBy('guard_name');
View:
#foreach($permissions as $guard => $perm)
<div class="form-group">
<label for="permission">Permissions ({{ ucfirst($guard) }}) {{ count($perm) }}</label>
<select name="permission[]" id="permission" class="form-control #error('permission') is-invalid #enderror" multiple>
#foreach($perm as $value)
<option value="{{ $value->id }}">{{ $value->name }}</option>
#endforeach
</select>
#error('permission')
<div class="invalid-feedback">
{{ $message }}
</div>
#enderror
</div>
#endforeach
Here is a more Laravel way to handle group by without the need to use raw statements.
$sources = $sources->where('age','>', 31)->groupBy('age');
$output = null;
foreach($sources as $key => $source) {
foreach($source as $item) {
//get each item in the group
}
$output[$key] = $source->count();
}

Resources