Laravel - Collections. How to separate array into 2 groups - php

I have created 2 collections(arrays) which each contain an array of 5 items/events.
$events = App\get_event_data( $args )
$collection = collect($events['events']);
$event_chunks = $collection->chunk(5);
$event_chunks->toArray();
#foreach ($event_chunks as $chunk)
Output of the above:
object(Illuminate\Support\Collection)[27632]
protected 'items' =>
array (size=2)
0 =>
object(Illuminate\Support\Collection)[27630]
protected 'items' =>
array (size=5)
...
1 =>
object(Illuminate\Support\Collection)[27631]
protected 'items' =>
array (size=5)
...
In my next loop, it simply goes through every item of the array 1 by 1.
I need to split the 5 items into a further 2 groups:
group of 2
group of 3
so I can wrap a div around each group.
Current loop:
#foreach ($chunk as $key => $event)
<div class="item">
{{ $event['title'] }}
</div>
#endforeach
What I need:
<div class="item-group">
[item1, item2]
</div>
<div class="item-group">
[item3, item4, item5]
</div>
Full code:
{{-- Get all events --}}
#if( $events = App\get_event_data( $args ) )
#php
$collection = collect($events['events']);
$event_chunks = $collection->chunk(5);
$event_chunks->toArray();
#endphp
#foreach ($event_chunks as $chunk)
<div class="{{ $block }}__flex-grid">
#foreach ($chunk as $key => $event)
<div class="item">
{{ $event['title'] }}
</div>
#endforeach
</div>
#endforeach
#endif

Assuming that you will allways have 5 items, a solution could be:
<div class="item-group">
#foreach (array_slice($chunk->toArray(),0,2) as $key => $event)
<div class="item">
{{ $event['title'] }}
</div>
#endforeach
</div>
<div class="item-group">
#foreach (array_slice($chunk->toArray(),2) as $key => $event)
<div class="item">
{{ $event['title'] }}
</div>
#endforeach
</div>
Or if want to avoid code duplication:
#php $chunk = [array_slice($chunk->toArray(),0,2), array_slice($chunk,2)];
#foreach ($chunk as $group)
<div class="item-group">
#foreach ($group as $key => $event)
<div class="item">
{{ $event['title'] }}
</div>
#endforeach
</div>
#endforeach
If you don't know or not sure that you have 5, you may need to change the logic of the chunks/slice.

It's maybe too late to answer, but I've made a function to split arrays into as groups as you like.
function SplitInto($array, $groups = 2)
{
$members = count($array) / $groups;
if (count($array) % $groups) $members = (int)(count($array) / $groups) + 1;
return array_chunk($array, $members);
}

Related

setting variables inside a Laravel foreach loop

I've just started using the framework. In plain PHP after the opening foreach I would then set the variables then close the php tag but then from what I can work out you have to then do the Laravel #foreach tags and then open and close #php. Is there a way around this as it seems like a lot of extra work and code?
#foreach($steps as $row)
#php
$title = $row->title;
$text = $row->text;
$i = 1;
#endphp
<div class="steps-item grid-wrap">
<div class="number"
#if($text || $title)
<div class="text-wrap">
#if($title)
<h2>{{$title}}</h2>
#endif
{!! $text !!}
</div>
#php
$i++;
#endphp
#endif
</div>{{--END steps-item--}}
#endforeach
Since blade is no PHP, you have to return to PHP with that directive. But you can set/use the variables without doing that in your case:
#foreach($steps as $i => $row)
<div class="steps-item grid-wrap">
<div class="number"
#if($text || $title)
<div class="text-wrap">
#if($title)
<h2>{{ $row->title }}</h2>
#endif
{!! $row->text !!}
</div>
#php
$i++;
#endphp
#endif
</div>{{--END steps-item--}}
#endforeach
If you still want to set variables, there's a Laravel package called alexdover/blade-set. But as #brombeer pointed out, in most cases it's highly recommended to set all necessary variables in the controller before passing them to the view.
Use laravel provided loop variables:
$loop->iteration The current loop iteration (starts at 1).
It will increment in every loop iteration automatically.
e.g:
First iteration = $loop->iteration => 1 ;
Second iteration = $loop->iteration => 2 ;
so on until loop ends.
Check docs:
The Loop Variables
You can use a #for directive with sizeof($steps) like that:
#for($i=0; $i<= sizeof($steps)-1; $i++)
#endfor
#foreach ($steps as $row)
<div class="steps-item grid-wrap">
<div class="number">
<div class="text-wrap">
#if ($row->title != '')
<h2>{{$row->title}}</h2>
/* if you want to display another title when its blank you can
use if-else here otherwise not need to use if conditions for
title and text */
#endif
#if ($row->text != '')
{!! $row->text !!}
#endif
</div>
</div>
</div>
#endforeach
{{--
for an example you have $steps values like
$steps =
Array(
[0] -> 1,
[1] -> 'title',
[2] -> 'text'
);
if you want this array key value pair you have to use #foreach like
#foreach ($steps as $key=>$value)
#endforeach
you can use key value in #foreach loop only
--}}

How to figure the question into 100 in relationship in laravel

I have two models 1. Subject 2. Question and it has One to many relation. And a student can choose many subjects he want. And now I want to take a test through the subjects. And the test should be 100 marks test.Now i need a way how to accomplish the 100 marks test. Suppose a student choose 3 subjects and if we divide 3 form 100 then it will be 33 (floor) or 34 (ceil) per subject but i want to round it to 100, how i accomplish this. Here is my code for getting the questionsn
foreach ($student->departments as $key => $department){
$majorSubjects[] =$department->subject_id;
}
$no_of_questions =100;
$uniqueSubjects=array_unique($majorSubjects);
$div = ceil($no_of_questions/count($uniqueSubjects));
$mul = $div*count($uniqueSubjects);
$subjects=Subject::whereIn('id',$majorSubjects)->get();
}
and in my blade
#foreach($subjects as $key => $subject)
<li class=" {{$key == 0 ? 'active' : ''}}">{{$subject->name}}</li>
#endforeach
</ul>
<div class="tab-content">
#if(!empty($subjects))
#foreach($subjects as $key => $subject)
<div class="tab-pane {{$key == 0 ? 'active' : ''}}" id="tab_{{ $subject->id }}">
#foreach($subject->questions->random($div) as $num => $question)
<form></form>
#endforeach
You can use modulus to get the remaining mark test.
$additional_mark_test = $no_of_questions % count($uniqueSubjects);
Put it in here.
foreach ($student->departments as $key => $department){
$majorSubjects[] =$department->subject_id;
}
$no_of_questions =100;
$uniqueSubjects=array_unique($majorSubjects);
$div = ceil($no_of_questions/count($uniqueSubjects));
$mul = $div*count($uniqueSubjects);
// Get the remaining test
$additional_mark_test = $no_of_questions % count($uniqueSubjects);
$subjects=Subject::whereIn('id',$majorSubjects)->get();
}
In your blade, this will check first if $additional_mark_test is empty.
#if(!empty($additional_mark_test))
#foreach($subject->questions->random($additional_mark_test) as $num => $question)
<form></form>
#endforeach
#php $additional_mark_test = 0; #endphp
#endif
Put it in here.
#foreach($subjects as $key => $subject)
<li class=" {{$key == 0 ? 'active' : ''}}">{{$subject->name}}</li>
#endforeach
</ul>
<div class="tab-content">
#if(!empty($subjects))
#foreach($subjects as $key => $subject)
<div class="tab-pane {{$key == 0 ? 'active' : ''}}" id="tab_{{ $subject->id }}">
#foreach($subject->questions->random($div) as $num => $question)
<form></form>
#endforeach
<!--Additional Mark Test(This will be add to first subject)-->
#if(!empty($additional_mark_test))
#foreach($subject->questions->random($additional_mark_test) as $num => $question)
<form></form>
#endforeach
#php $additional_mark_test = 0; #endphp
#endif

Is it possible to have 3 div elements and have your loop fill them in order?

Usually when I loop through a database table records, I put them in 1 div, however, I have been wondering whether it is possible to create 3 divs and then put one record in each div, then start from the first div again and rinse and repeat.
Example of how I've done it so far:
<div class="container">
#foreach($albumImages as $albumImage)
<div class="centeredImage stickyContainer" style="background-image: url('/storage/uploads/albums/{{$albumName}}/{{$albumImage->file_name}}')">
<a class='specialA' href=''></a>
</div>
#endforeach
</div>
As you can see in this case, all the records are in the container div.
Example of what I've been thinking about:
<div class="flex-grid">
<div class="col-l"></div>
<div class="col-c"></div>
<div class="col-r"></div>
</div>
and have the first record go in col-l, the second in col-c, the third in col-r and then start from col-l again.
Try this
<div class="flex-grid">
#php($count = 0)
#foreach($albumImages as $albumImage)
#if ($count % 3 == 0)
<div class="col-l"></div>
#elseif($count % 3 == 1)
<div class="col-c"></div>
#else
<div class="col-r"></div>
#endif
#php($count++)
#endforeach
</div>
You can use this code but I later will update my answer with more good solution
#php($count = 0)
#foreach($albumImages as $albumImage)
#if ($count % 3 == 0)
#php($albumImages1[] = $albumImage)
#elseif($count % 3 == 1)
#php($albumImages2[] = $albumImage)
#else
#php($albumImages3[] = $albumImage)
#endif
#php($count++)
#endforeach
#if (!empty($albumImages1))
#foreach($albumImages1 as $albumImage)
// your logic here
#endforeach
#endif
#if (!empty($albumImages2))
#foreach($albumImages2 as $albumImage)
// your logic here
#endforeach
#endif
#if (!empty($albumImages3))
#foreach($albumImages3 as $albumImage)
// your logic here
#endforeach
#endif
Also you can split three part your initial array make global helper functions.
define global function
function split_sequence_by_count ($array, $count) {
$result = [];
for ($i = 0; $i < $count; $i++) {
$result[$i] = [];
}
$_count = 0;
foreach ($array as $current) {
$index = $_count % 3;
$result[$index][] = $current;
$_count++;
}
return $result;
}
usage in blade
#php(list ($albumImages1, $albumImages2, $albumImages3) = split_sequence_by_count($albumImages, 3))
#foreach($albumImages1 as $albumImage)
// your logic here
#endforeach
#foreach($albumImages2 as $albumImage)
// your logic here
#endforeach
#foreach($albumImages3 as $albumImage)
// your logic here
#endforeach
Another way would be array_chunk then just run through the array with 2 nested loops. Should be self-explaining.
<?php
$people =
[
'John',
'Paul',
'Ringo',
'George'
];
$i=0;
$classes = ['col-a','col-b','col-c'];
foreach($people as $name) {
$class = $classes[$i++%3];
?>
<div class='<?=$class?>'>
<?=$name?>
</div>
<?php
}
Formatted output:
<div class='col-a'>
John
</div>
<div class='col-b'>
Paul
</div>
<div class='col-c'>
Ringo
</div>
<div class='col-a'>
George
</div>
Regarding placing each name in each column (as per your comment), we could wrangle the array format:
$classes = ['col-a','col-b','col-c'];
$i=0;
foreach($people as $name)
$columns[$classes[$i++%3]][] = $name;
?>
<?php foreach($columns as $class=>$column) { ?>
<div class='<?=$class?>'>
<?php foreach($column as $name) { ?>
<div class="name">
<?=$name?>
</div>
<?php } ?>
</div>
<?php } ?>
Formatted output:
<div class='col-a'>
<div class="name">
John
</div>
<div class="name">
George
</div>
</div>
<div class='col-b'>
<div class="name">
Paul
</div>
</div>
<div class='col-c'>
<div class="name">
Ringo
</div>
</div>

Laravel multidimensional echo values?

I get errors in laravel how do I echo the values correctly. I have this multidimensional array. This is the controller:
$data = array('names'=>$names, 'fruits'=>$fruits);
return view('content', [
'data' => $data
]);
and here is where I echo the values:
#section('content')
<div class="row">
<div class="col-md-12">
#foreach ($data as $row)
{{$row['fruits']}}
#endforeach
</div>
</div>
#endsection
You can send an array with key and values to your views. The key will be the variable name in your view. This is all very basic Laravel stuff and you can read more about it in the docs.
The controller:
$data = array('names'=>$names, 'fruits'=>$fruits);
return view('content', $data);
You view:
#section('content')
<div class="row">
<div class="col-md-12">
#foreach ($fruits as $fruit)
<!-- Do stuff with $fruit -->
#endforeach
</div>
</div>
#endsection
If you want to loop over them you could do that with your original controller, but this is how it would look in your view:
#section('content')
<div class="row">
<div class="col-md-12">
#foreach ($data as $item)
{{ $item }}
#endforeach
</div>
</div>
#endsection
This will only work if $fruits and $names are convertible to strings. Otherwise you would get an error.
$data is also an array. Access it's values with the keys $data["fruits"] or $data["names"]. If you want to loop through the $fruits-array just use a foreach-loop in your template:
foreach ($data["fruits"] as $key => $value) {
// make something with the fruit-entries.
}

How to loop through this array in Laravel?

I am working on a web application using laravel 5.3, I got one problem.
I want to loop through this array.
What I tried is:
Controller:
public function postSearch(Request $request)
{
$categoryid = $request->category_id;
$locationid = $request->location_id;
$category = Category::where('id', $categoryid)->first();
$cities = Location::where('id', $locationid)->pluck('city');
$cityname = $cities[0];
$alllocations = [];
$ratecards = [];
$locations = [];
$father = [];
$i = 0;
$filteredlocations = $category->locations->where('city', $cityname)->all();
foreach($filteredlocations as $location){
$alllocations[$i] = $location->getaddetails;
$ratecards[$i] = $location->ratecard;
$i++;
}
$father[0] = $alllocations;
$father[1] = $ratecards;
return view('ads', compact('father'));
}
View is here:
#foreach($father as $key => $f)
#foreach($f as $key => $arr)
#if (isset($arr->adName))
<div class="post">
{{Html::image($arr->path,'Ad Picture',array('class' => 'ad-image'))}}
<h2 class="post-title">{{ $arr->adName }}</h2>
<p class="description">{{ $arr->description }} </p>
<div class="post-footer">
<span class="categories">
<ul class="cats">
<li class="btn btn-default">Price :
{{ $f[$key]->monthly_rate }}
</li>
<li class="btn btn-default">Status:
#if($arr->status == 1)
<p>Active</p>
#else
<p>Not-Active</p>
#endif
</li>
<li>view details</li>
</ul>
</span>
</div>
</div>
#endif
#endforeach
#endforeach
Problem:
Okay problem is when I try to get {{ $f[$key]->monthly_rate }} which is the 2nd array i.e RateCards I get nothing. I want to get the Rate Card array and from that array mothly_rate which is a field in there.
Thanks
PS : {{ $f[$key]->monthly_rate }} this return nothings in view.
The problem is that $f[$key] is an array of two objects.
That means that the properties youre looking for are inside each of those items, like this:
$f[$key][0]->monthly_rate
$f[$key][1]->monthly_rate
You will have to loop those objects to get their properties values.

Categories