Instead an element in a Laravel Colletion each 3 elements - laravel

I have a collection with 4 Object :
Collection{#645 ▼
#items: array:4 [▼
0 => Team {#644 ▶}
1 => Team {#613 ▶}
2 => Team {#607 ▶}
3 => Team {#599 ▶}
]
}
I would like to insert a element each 3, begining by 0 index ( In this case, it would be in 0, and 3)
How should I do it???
The push method doesn't allow me to insert between to elements....

Use the map() helper. I've tested this and it works perfectly:
$counter = 0;
$collection->map(function($i) use(&$counter) {
if ($counter % 3 === 0) {
$i->custom = 'Custom value';
}
$counter++;
return $i;
});

Related

Sum collection variables

i have the next collection:
It is grouped by zone and fundo and I need to sum all the sup_ha that each fundo contains
$transporFundo = $tansporCollect->groupBy(['zona','fundo']);
foreach ($transporFundo as $fundo) {
$supFundo = $fundo->sum('sup_ha');
dd($supFundo);
}
that is to say that for example of my collection for zona 1 and fundo 805 I would have to add the sup_ha field of the 364 records that are seen.
I tried to do it but I don't know how to access the field, as seen in my code I tried and it returns 0.
I hope you can help me, thanks
**
UPDATE
**
ok, remove the group by, for example show a collection like the following, the original has 700k of records
Illuminate\Support\Collection {#778646 ▼
#items: array:4 [▼
0 => array:3 [▼
"zona" => 1
"sup_ha" => 20
"fundo" => 805
]
1 => array:3 [▼
"zona" => 1
"sup_ha" => 10
"fundo" => 805
]
2 => array:3 [▼
"zona" => 2
"sup_ha" => 5
"fundo" => 800
]
3 => array:3 [▼
"zona" => 2
"sup_ha" => 10
"fundo" => 900
]
]
}
so, I need the sum of the sup_ha of equal fundo, like this:
fundo | sum
805 | 30
800 | 5
900 | 10
And I need the sum of the sup_ha of equal zona, like this:
zona | sum
1 | 30
2 | 15
Given this, that's why I had made a group by to calculate the sum of the fundo's. so now I don't know whether to think if it was right to do it like this
I hope you have clarified
Assuming your collection is assigned as $collection
$zonaArray = [];
$fundoArray = [];
$sum = 0;
foreach ($collection as $key => $t) {
if (!in_array($t['zona'], $zonaArray)) {
$zonaArray[$key]['zona'] = $t['zona'];
$zonaArray[$key]['sum'] = (float) $t['sup_ha'];
} else {
$zonaArray[$key]['sum'] = (float) $t['sup_ha'];
}
if (!in_array($t['fundo'], $fundoArray)) {
$fundoArray[$key]['fundo'] = $t['fundo'];
$fundoArray[$key]['sum'] = (float) $t['sup_ha'];
} else {
$fundoArray[$key]['sum'] = (float) $t['sup_ha'];
}
}
$checkzona = [];
$value = 0;
$finalZone = [];
$i = 0;
foreach ($zonaArray as $key => $val) {
if (in_array($val['zona'], $checkzona)) {
unset($finalZone[$i - 1]);
$val['sum'] = $value + (float) $val['sum'];
$finalZone[$i] = $val;
$i++;
} else {
$checkzona[] = $val['zona'];
$value = $val['sum'];
$finalZone[$i] = $val;
$i++;
}
}
Your zone wise sum output is looking like below.
array:2 [▼
1 => array:2 [▼
"zona" => 1
"sum" => 30.0
]
3 => array:2 [▼
"zona" => 2
"sum" => 15.0
]
]
For fundo sum:
$checkfundo = [];
$valuefundo = 0;
$finalFundo = [];
$k = 0;
foreach ($fundoArray as $key => $fundo) {
if (in_array($fundo['fundo'], $checkfundo)) {
unset($finalFundo[$k - 1]);
$fundo['sum'] = $valuefundo + (float) $fundo['sum'];
$finalFundo[$k] = $fundo;
$k++;
} else {
$checkfundo[] = $fundo['fundo'];
$valuefundo = $fundo['sum'];
$finalFundo[$k] = $fundo;
$k++;
}
}
Your fundo wise sum output is looking like below.
array:3 [▼
1 => array:2 [▼
"fundo" => 805
"sum" => 30.0
]
2 => array:2 [▼
"fundo" => 800
"sum" => 5.0
]
3 => array:2 [▼
"fundo" => 900
"sum" => 10.0
]
]
I hope it's working for you.
Assuming your collection is assigned to $collection.
so, I need the sum of the sup_ha of equal fundo.
High order functions
return $collection->groupBy('fundo')->map->sum('sup_ha');
Alternative
return $collection
->groupBy('fundo')
->transform(function (Collection $sub) {
return $sub->sum('sup_ha');
});
It prints
{
"805": 30,
"800": 5,
"900": 10
}
And I need the sum of the sup_ha of equal zona
High order functions
return $collection->groupBy('zona')->map->sum('sup_ha');
Alternative
return $collection
->groupBy('zona')
->transform(function (Collection $sub) {
return $sub->sum('sup_ha');
});
It prints
{
"1": 30,
"2": 15
}

adding multiple scopes to nested eager loading

In my application users can predict scores of upcoming soccer games.
Basically I want to display all the user predictions for this week. I do this by adding a scope to my match model that only loads matches from this week.
Problem: I'm still getting all my predictions from that user (not only the ones from the current week) For predictions that my user created this week, the correct match is loaded. For the other predictions there is no match but they still get put in my query.
How can I add another scope to my nested eager loading that will only select predictions made during this week or have a match that is not null? (or other solution)
Code:
public function showPredictions() {
$user = auth()->user()->load(['predictions.match' => function ($query) { $query->thisWeek();}]);
dd($user);
return view('predictions', compact('user'));
}
Match model
public function Predictions() {
return $this->hasMany('App\Prediction', 'match_id', 'match_id');
}
public function scopeThisWeek($query) {
$start_date = now()->previous(Carbon::TUESDAY);
$end_date = now()->next(Carbon::MONDAY);
return $query->whereDate('date','>', $start_date)->whereDate('date','<', $end_date);
}
output
#relations: array:1 [▼
"predictions" => Collection {#265 ▼
#items: array:29 [▼
0 => Prediction {#268 ▶}
1 => Prediction {#269 ▶}
2 => Prediction {#270 ▶}
3 => Prediction {#271 ▶}
4 => Prediction {#272 ▶}
5 => Prediction {#273 ▶}
6 => Prediction {#274 ▶}
7 => Prediction {#275 ▶}
8 => Prediction {#276 ▶}
9 => Prediction {#277 ▶}
10 => Prediction {#278 ▶}
11 => Prediction {#279 ▶}
12 => etc...
]
Output I want to achieve (I have 10 predictions for each user that week)
#relations: array:1 [▼
"predictions" => Collection {#265 ▼
#items: array:10 [▼
0 => Prediction {#268 ▶}
1 => Prediction {#269 ▶}
2 => Prediction {#270 ▶}
3 => Prediction {#271 ▶}
4 => Prediction {#272 ▶}
5 => Prediction {#273 ▶}
6 => Prediction {#274 ▶}
7 => Prediction {#275 ▶}
8 => Prediction {#276 ▶}
9 => Prediction {#277 ▶}
10 => Prediction {#278 ▶}
]
I have a relation field in my predictions array with the correct match in.
Use whereHas():
$user = auth()->user()->load([
'predictions' => function ($query) {
$query->whereHas('match', function ($query) {
$query->thisWeek();
});
},
'predictions.match'
]);

Foreach giving me data for the first loop and empty collection onwards

I have a foreach in my controller passed to the view:
public function index()
{
$budgets=\App\Budget::all();
$transactions=\App\Transaction::select('transaction_ammount');
foreach($budgets as $budget){
$budgetThisCategory[$budget->id]=$transactions->whereMonth('transaction_date',Carbon::today()->format('m'))->where('category_id',$budget->category_id)->get();
}
return view('budgets.index',compact('budgets','id','transactions','budgetThisCategory'));
}
When I dd my view, I get the following:
array:2 [▼
1 => Collection {#832 ▼
#items: array:6 [▼
0 => Transaction {#825 ▶}
1 => Transaction {#826 ▶}
2 => Transaction {#827 ▶}
3 => Transaction {#828 ▶}
4 => Transaction {#829 ▶}
5 => Transaction {#830 ▶}
]
}
2 => Collection {#868 ▼
#items: []
}
]
So I only get my first foreach collection but not my second one. There is data in the second one. Indeed if I change in my controller and add a orderbydesc('$budget_id') I will get this second collection, but not the first one.
What am I doing wrong? I am quite new to this, and I am sure that the way to solve this is simple. But I do not really know what's the problem.
Matthew thanks for the answer. You have put me in a path that I didn't know that it existed. I have changed all that foreach into a complety different thing, more beautiful and simple. Plus I have added some functionality. I suposed that there are better ways to do it. But I am really happy of where I have arrived.
$budgets=\App\Budget::get();
foreach($budgets as $budget){
$budgetCount[$budget->id]=$budget->find($budget->id)->transactions()->whereMonth('transaction_date',Carbon::today()->format('m'))->count();
$budgetSum[$budget->id]=$budget->find($budget->id)->transactions()->whereMonth('transaction_date',Carbon::today()->format('m'))->sum('transaction_ammount');
}

Laravel - Sortby date after GroupBy callback

I'm creating a collection and using a groupBy to group items together depending on the month, however after this I then want to it to go back to ascending date order (Jan/Feb/Mar). Here is my function that I'm using below;
private function monthByMonthAgentReferrals() {
$case = Case::where('start_date', '>', Carbon::now()->subDays(360))
->where('source', 'AGENT')->get()
->groupBy(function($key) {
return Carbon::parse($key->start_date)->format('m');
});
return $case;
}
At the moment when I display the results I get a return of the months in a random order;
Collection {#1982 ▼
#items: array:12 [▼
12 => Collection {#1321 ▶}
"07" => Collection {#1322 ▶}
10 => Collection {#1320 ▶}
"05" => Collection {#1991 ▶}
"06" => Collection {#1990 ▶}
"08" => Collection {#1989 ▶}
"01" => Collection {#1988 ▶}
11 => Collection {#1987 ▶}
"09" => Collection {#1986 ▶}
"02" => Collection {#1985 ▶}
"03" => Collection {#1984 ▶}
"04" => Collection {#1983 ▶}
]
}
How would I go about sorting by 'start_date' again? or would it be better to sort by the array key? Thanks.
You can use it like this:
$case = Case::where('start_date', '>', Carbon::now()->subDays(360))
->selectRaw('table_name.*')
->where('source', 'AGENT')
->groupBy(function($key) {
return Carbon::parse($key->start_date)->format('m');
})->orderBy('start_date')->get();
private function monthByMonthAgentReferrals() {
$case = Case::where('start_date', '>', Carbon::now()->subDays(360))
->where('source', 'AGENT')->get()
->groupBy(function($key) {
return Carbon::parse($key->start_date)->format('m');
})->toArray();
ksort($case);
return collect($case);
}
Converts the collection to an array, use the function ksort on the array and then recollect the array.

Return records where children are under parents

I am retriving model like this $people = Person::with('children')->get(); and this returns me dd($people);
Collection {#322 ▼
#items: array:4 [▼
0 => Person {#311 ▶}
#relations: array:1 [▼
"children" => Collection {#320 ▼
#items: array:2 [▼
0 => Child {#323 ▶}
1 => Child {#324 ▶}
1 => Person {#312 ▶}
2 => Person {#313 ▶}
#relations: array:1 [▼
"children" => Collection {#320 ▼
#items: array:2 [▼
0 => Child {#323 ▶}
3 => Person {#314 ▶}
But now i am trying to export this to excel ( Maatwebsite/Laravel-Excel with view ) but i needed to be like this (children under their parent), for example:
Collection {#322 ▼
#items: array:6 [▼
0 => Person {#311 ▶} // Parent 1
1 => Child {#312 ▶} // Child of parent 1
2 => Child {#313 ▶} // Child of parent 1
3 => Person {#314 ▶} // Parent 2 - Single (no relation)
4 => Person {#315 ▶} // Parent 3
5 => Child {#316 ▶} // Child of parent 3
6 => Person {#314 ▶} // Parent 4 - Single (no relation)
Im not sure on how to do this (Eloquent or Query Builder) ?
I didn't try but something like this would work I guess:
$c = collect([]);
foreach($people as $person)
{
$children = $person->children;
$c->add($person);
if(count($children) > 0)
{
foreach($children as $child)
{
$c->add($child);
}
}
}
dd($c);

Resources