Laravel: How can I use Group By within my view? - laravel-5

I am trying to get all students, then group them by graduation year. Within my view, I want to have a headline of the year:
<h2>2016</h2>
<ul>
<li>Last, First</li>
...
</ul>
<h2>2017</h2>
<ul>
<li>Last, First</li>
...
</ul>
I believe I am close, but not sure of the "Laravel way". The data looks good - as in, the query is getting/grouping correctly, I think my struggle is understanding how to loop through the collection.
MyController.php
public function index()
{
$students = Student::all()->groupBy('grad_year');
return view('student.index', compact('students'));
}
In my view I can see I am getting this:
MyView.blade.php
{{dd($students)}}
Collection {#178 ▼
#items: array:2 [▼
2016 => Collection {#173 ▼
#items: array:3 [▼
0 => Student {#180 ▶}
1 => Student {#181 ▶}
2 => Student {#182 ▶}
]
}
2017 => Collection {#172 ▶}
]
}
SOLUTION
Here is what my view looks like to get the output I wanted.
MyView.blade.php
#foreach ($collection as $year => $students)
<p>{{$year}}</p>
<ul class="list-unstyled">
#foreach($students as $student)
<li>{{ $student->last_name }}, {{ $student->first_name }}</li>
#endforeach
</ul>
#endforeach

something like:
$studentsByYear = $students;
foreach ($studentsByYear as $year => $students) {
echo "<h2>$year</h2>";
echo "<ul>";
foreach ($students as $student) {
echo "<li>".$student->name."</li>";
}
echo "</ul>";
}

Related

I have a collection of objects in laravel. When I try to access it in blade it shows "Attempt to read property "year_month" on array"

^ Illuminate\Support\Collection {#1471 ▼
#items: array:9 [▼
0 => {#1490 ▼
+"year_month": "2022-01"
}
1 => {#1452 ▼
+"year_month": "2022-02"
}
2 => {#526 ▼
+"year_month": "2022-03"
}
3 => {#1453 ▼
+"year_month": "2022-04"
}
4 => {#1457 ▼
+"year_month": "2022-05"
}
5 => {#1458 ▼
+"year_month": "2022-06"
}
6 => {#1461 ▼
+"year_month": "2022-07"
}
7 => {#1463 ▼
+"year_month": "2022-08"
}
8 => {#1460 ▼
+"year_month": "2022-09"
}
]
#escapeWhenCastingToString: false
}
This is my collection. And I try to access it in Blade as
#if(!empty($monthYears))
<div class="pt-2 pb-2 carousel">
#foreach($monthYears as $monthYear)
<div wire:click="changePeriod('{{$monthYear->year_month}}')" class="text-gray-700 text-base mx-4 cursor-pointer carousel-cell #if($loop->index == count($monthYears)-2) is-clicked #endif">
{{date("m/y", strtotime($monthYear->year_month))}}
</div>
#endforeach
</div>
#endif
On the first load it loads without any issue. But when I click on any events of livewire components it shows "Attempt to read property "year_month" on array".
Here's my livewire component
public Collection $monthYears;
public function mount()
{
$this->monthYears = DB::table('table_name')->orderBy('year_month', 'asc')->groupBy('year_month')->get('year_month');
}
Livewire does not hydrate stdClass properties. They will be converted to array structure.
Note the supported types.

Laravel - Undefined index: current_timestamp in Nested foreach

In my Laravel-5.8, I am trying to use Nested foreach statement in the view blade:
I have this controller:
public function index()
{
try{
$client = new Client();
$res = $client->request('GET','https://example.com/tracking/JKK998', [
'query' => ['key' => 'jkkkm7725']
])->getBody();
$geoLocation = json_decode($res->getContents(), true);
$geoLocationData = collect($geoLocation)->sortBy(function ($data) {
return Carbon::parse($data['current_timestamp'])->format('d-m-Y h:i:s');
})->all();
$currentLocation = collect($geoLocation)->sortByDesc(function ($data) {
return Carbon::parse($data['current_timestamp'])->format('d-m-Y h:i:s');
})->first();
$currentLocationGroup = collect($geoLocation)->groupBy(function ($data) {
return Carbon::parse($data['current_timestamp'])->format('d-m-Y');
})->all();
$currentLocationFilter = explode(',', $currentLocation['current_coord'] ?? '');
return view('index', [
'currentLocation' => $currentLocation,
'currentLocationGroup' => $currentLocationGroup,
'currentLocationFilter' => $currentLocationFilter,
'geoLocation' => $geoLocation,
'geoLocationData' => $geoLocationData
]);
}catch (Exception $exception) {
Log::error($exception);
return back();
}
}
dd($currentLocationGroup);
gives:
array:14 [▼
"22-06-2020" => Illuminate\Support\Collection {#297 ▼
#items: array:25 [▼
0 => array:30 [▼
"current_timestamp" => "2020-06-22T11:53:29Z"
"trip_status" => "DISPATCHED"
]
1 => array:31 [▶]
2 => array:31 [▶]
...
While dd($geoLocationData); gives:
array:554 [▼
0 => array:30 [▼
"current_timestamp" => "2021-01-22T12:30:25.4698261Z"
"client_tracking_id" => "ddd3321"
"current_asset_position_name" => "2, Adelaide, Australia"
"trip_status" => "DISPATCHED"
]
1 => array:31 [▼
"current_timestamp" => "2021-02-23T20:51:50.3066741Z"
"client_tracking_id" => "TRIP-20200621007"
"current_asset_position_name" => "20, Adelaide, Australia"
"trip_status" => "AROUND CUSTOMER LOCATION"
]
....
View blade:
#foreach($currentLocationGroup as $groupValue)
<div class="time-label">
<span class="bg-red">{{ \Carbon\Carbon::parse($groupValue['current_timestamp'])->format('d-m-Y') }}</span>
</div>
#foreach($geoLocationData as $value)
#if(\Carbon\Carbon::parse($groupValue['current_timestamp'])->format('d-m-Y') == \Carbon\Carbon::parse($value['current_timestamp'])->format('d-m-Y') )
<div>
<i class="fas fa-truck bg-green"></i>
<div class="timeline-item">
<span class="time"><i class="fas fa-clock"></i> {{ \Carbon\Carbon::parse($value['current_timestamp'])->diffForHumans() ?? 'N/A' }}</span>
<h3 class="timeline-header no-border">Trip Status: {{ $value['trip_status'] }} </h3>
<div class="timeline-body">
<p>Location: <b>{{ $value['current_name'] ?? '' }}</b></p>
<p>Time: <b>{{ \Carbon\Carbon::parse($value['current_timestamp'])->format('d-m-Y h:i:sA') ?? 'N/A' }}</b></p>
</div>
</div>
</div>
#endif
endforeach
But I got this error:
ErrorException
Undefined index: current_timestamp
C:\xampp\htdocs\tracking-app\vendor\laravel\framework\src\Illuminate\Collections\Collection.php:1414
public function offsetExists($key)
{
return isset($this->items[$key]);
}
But it exists.
How do I get this resolved?
Thanks

Putting specific arrays values into a Laravel view table

I have this nested array under the variable $audits which I hand over to a Laravel 5.8 view:
array:4 [▼
0 => array:3 [▼
"action" => "Case initiated by:"
"user" => "Doe, Jane"
"timestamp" => Carbon #1558353758 {#419 ▶}
]
1 => array:3 [▼
"action" => "New head mediator:"
"user" => "Doe, Jane"
"timestamp" => Carbon #1558353758 {#430 ▶}
]
2 => array:3 [▼
"action" => "Case closed by:"
"user" => "Doe, Jane"
"timestamp" => Carbon #1558353787 {#467 ▶}
]
3 => array:3 [▼
"action" => "Case re-opened by:"
"user" => "Doe, Jane"
"timestamp" => Carbon #1558353791 {#474 ▶}
]
]
My goal is to fill a table in the view to get the following output:
Action User Date/time (UTC)
-------------------------------------------------------
Case initiated by: Doe, Jane 2019-05-20 12:02:38
New head mediator: Doe, Jane 2019-05-20 12:02:38
Case closed by: Doe, Jane 2019-05-20 12:03:07
Case re-opened by: Doe, Jane 2019-05-20 12:03:11
To achieve that, I had hoped to be able to loop through like this:
<table>
<th>Action</th>
<th>User</th>
<th>Date/time (UTC)</th>
#foreach ($audits as $audit)
#foreach ($audit as $value)
<tr>
<td>{{ $value['action'] }}</td>
<td>{{ $value['user'] }}</td>
<td>{{ $value['timestamp'] }}</td>
</tr>
#endforeach
#endforeach
</table>
However, this will give me error messages since the view doesn't seem to be able to retrieve such specific values from arrays as it can only handle strings.
So, I tried to transform the array into objects, use JSON encoding etc. but to no avail.
The way the array gets constructed in the controller is like this (maybe somebody can point me in a direction how to make a proper collection or object so that it can be handled better by the view):
public function show(Project $project)
{
$audits_raw= $project->audits;
foreach ($audits_raw as $audit_raw) {
foreach ($audit_raw->new_values as $action => $id) {
if ($action == 'initiator_id') {
$actions[] = 'Case initiated by:';
$users[] = $this->userName($id);
$timestamps[] = $audit_raw->updated_at;
} elseif ($action == 'head_mediator_id') {
$actions[] = 'New head mediator:';
$users[] = $this->userName($id);
$timestamps[] = $audit_raw->updated_at;
} elseif ($action == 'marked_for_deletion' && $id == 1) {
$actions[] = 'Case closed by:';
$users[] = $this->userName($audit_raw->user_id);
$timestamps[] = $audit_raw->updated_at;
} elseif ($action == 'marked_for_deletion' && $id == 0) {
$actions[] = 'Case re-opened by:';
$users[] = $this->userName($audit_raw->user_id);
$timestamps[] = $audit_raw->updated_at;
}
}
}
$audits = array_map(function ($action, $user, $timestamp) {
return array_combine(
['action', 'user', 'timestamp'],
[$action, $user, $timestamp]
);
}, $actions, $users, $timestamps);
return view('admin.billing.show', compact('project', 'audits', 'actions'));
}
protected function userName($id)
{
$user = User::where('id', $id)->first();
$username = $user->last_name.', '.$user->first_name;
return $username;
}
Many thanks in advance!
Change the view.
#foreach($audits as $key)
<tr>
<td>{{ $key['action'] }}</td>
<td>{{ $key['user'] }}</td>
<td>{{ Carbon\Carbon::parse($key['timestamp'])->format('Y-m-d H:i:s') }} .
</td>
</tr>
#endforeach

Get id of collection in foreach

I'm trying to get the ID of the share, but, I'm do a foreach in links, look:
#foreach($user->getRelation('shares')->pluck('links') as $link)
{{ $link->first()->title }} //works
{{ //get the ID, of the current share }}
#endforeach
How can I do it?
dd($user->shares);
Collection {#338 ▼
#items: array:3 [▼
0 => Share {#343 ▼
#attributes: array:6 [▼
"id" => 7
"link_id" => 3
"user_id" => 1
"shared_in" => null
"content" => "testetste"
"created_at" => "2018-02-02 15:46:13"
]
#relations: array:1 [▼
"links" => Collection {#349 ▶}
]
}
1 => Share {#344 ▶}
2 => Share {#345 ▶}
]
}
You can specify id as the second parameter for pluck() method:
#foreach($user->getRelation('shares')->pluck('links', 'id') as $id => $link)
{{ $link->first()->title }}
{{ $id }}
#endforeach
In this instance, your shares? are already shared with the view in their entirety and so plucking the links and ids doesn't really save you much performance meaning this loop is unnecessarily complicated.
#foreach($user->getRelation('shares') as $share)
{{ $share->links->first()->title }}
{{ $share->id }}
#endforeach
If however, all you want to use in this view instance is the link and id, then I would recommend modifying your query in the controller to reduce the size of the overall collection being sent to your view instance.

Recursing nested array in blade template

I am attempting to loop out a menu in Laravel.
I am passing the nested array to the main blade template categories-management.blade.php.
View::make('categories-management')->with('categories', $categories);
Where $categories is
array (size=3)
'Business Resources' =>
array (size=7)
'Operations' =>
array (size=4)
'resource_type_id' => int 1
27 =>
array (size=3)
'id' => int 27
'name' => string 'Design & Development' (length=20)
'children' =>
array (size=2)
... truncated ...
I am then kicking of the menu inside of categories-management.blade.php with this:
#include('/includes/category-menu-item', array('categories', $categories))
Inside includes/category-menu-item I have the following loop:
#if(is_array($categories))
<ul>
#foreach($categories as $key => $value)
<li>
#if(!is_numeric($key))
<p>{{$key}}</p>
#include('/admin/includes/category-menu-item', array('categories', $value))
#else
<button data-category-id="{{$value->id}}">{{$value->name}}</button>
#include('/admin/includes/category-menu-item', array('categories', $value->children))
#endif
</li>
#endforeach
</ul>
#endif
This is still obviously incomplete but I already have issues where the template never gets past the first layer and prints out:
Business Resources
Business Resources
Business Resources
Business Resources
... etc ...
How do I get Laravel to recognise the new array value? Or is there a better method for this?
Your #include statements are not correct. The data passed to view need to be an associated array, you have passed an array with numeric keys. You have to change from array('categories', $value) into array('categories' => $value):
#if(is_array($categories))
<ul>
#foreach($categories as $key => $value)
<li>
#if(!is_numeric($key))
<p>{{$key}}</p>
#include('/admin/includes/category-menu-item', array('categories' => $value))
#else
<button data-category-id="{{$value->id}}">{{$value->name}}</button>
#include('/admin/includes/category-menu-item', array('categories' => $value->children))
#endif
</li>
#endforeach
</ul>
#endif

Resources