adding multiple scopes to nested eager loading - laravel

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'
]);

Related

How to transpose this into an array?

I am trying to transpose a Collection into an array. I'm not sure what's the method to do this. I think it's due to my lack of understanding in the eloquent operators/commands. I've been trying with map but had not made any headway.
Data
Collection {#911 ▼
#items: array:4 [▼
"HIGH" => Collection {#902 ▼
#items: array:2 [▼
0 => Finding {#680 ▶}
1 => Finding {#681 ▶}
]
}
"MEDIUM" => Collection {#903 ▶}
"LOW" => Collection {#904 ▶}
"INFO" => Collection {#905 ▶}
]
}
I would like to transpose this into an array ['HIGH' => 2, 'MEDIUM' => 1, 'LOW' => 13 ...]
I tried to apply a map but it's not giving me what i want. (tried applying the below)
... ->map (function ($risk) { return $risk[0]; });
Looking for tips on learning about these map operators and also how to transpose the Collection result above. Any help will be the most welcome!
Use toArray function to convert the collection to the array
$collection = collect(['name' => 'Desk', 'price' => 200]);
$collection->toArray();
Hope this link helps you.
https://laravel.com/docs/5.7/collections#method-toarray

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.

Instead an element in a Laravel Colletion each 3 elements

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;
});

Laravel 5.3 convert query builder to LengthAwarePaginator

I need to use switch cases to add constraints to the query I need to run. I need it to work with pagination, I tried this:
$albums = Album::with(array(
'images' => function ($query) {
$query->orderBy('order', 'asc');
}
))
->where('votes.votable_type','App\Models\Album')
->groupBy('albums.id');
$albums->published()->orderBy('created_at', 'desc')->paginate(30);
dd($albums);
and I get
Builder {#361 ▼
#query: Builder {#350 ▶}
#model: Album {#351 ▶}
#eagerLoad: array:2 [▶]
#macros: array:5 [▶]
#onDelete: Closure {#364 ▶}
#passthru: array:11 [▶]
#scopes: array:1 [▶]
#removedScopes: []
}
If I run
$albums = Album::with(array(
'images' => function ($query) {
$query->orderBy('order', 'asc');
}
))
->where('votes.votable_type','App\Models\Album')
->groupBy('albums.id')
->published()->orderBy('created_at', 'desc')->paginate(30);
dd($albums);
I get
LengthAwarePaginator {#467 ▼
#total: 97
#lastPage: 4
#items: Collection {#872 ▶}
#perPage: 30
#currentPage: 1
#path: "http://images.dev"
#query: []
#fragment: null
#pageName: "page"
}
why is there difference between these two approaches? I need to use first approach to be able to add constraints using switch case, I can't do that using second approach. But with first approach I do not get LengthAwarePaginator, how to fix it so that I get that?
You should redeclare the variable $albums if you wish it to be saved to this variable. Change this:
$albums->published()->orderBy('created_at', 'desc')->paginate(30);
To:
$albums = $albums->published()->orderBy('created_at', 'desc')->paginate(30);

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