I have a database search that returns thousands of entries which I then group by two columns like so:
$results = $merged->groupBy(['source', 'parent']);
The result is Laravel Collection with the following structure, grouped first by the 'source' (1_k12_fill_trypsin_dig), then the 'parent' (2, 4, 9, 10...), and each 'parent' has some number of children:
I want to sort the parents by the number of children they have. So, in this example, I would want '4' to be at the top, so that the child count serves as the 'truth test' in some closure. I just don't know how to access these elements. I was hoping to use Collection methods as opposed to looping through with vanilla PHP.
Have you tried sorting by their count?
Sort by source count
$merged
->groupBy(...)
->sort(function ($sources) {
return collect($sources)->count();
});
Sort by parent count
$merged
->groupBy(...)
->sort(function ($sources) {
return collect($sources)
->sum(function ($parents) {
return count($parents);
});
});
To sort only the nested array, you could use map() or transform().
$merged
->groupBy(['source', 'parent'])
->map(function ($source) {
return collect($source)
->sortByDesc(function ($parent) {
return count($parent);
})
->all();
});
// PHP 7.4+
$merged
->groupBy(['source', 'parent'])
->map(fn($source) =>
collect($source)
->sortByDesc(fn($parent) => count($parent))
->all()
);
I used Faker to generate collections similar to yours and it worked for me.
Related
I'm filtering out non-unique arrays from my collection based only on a combination of if the "first_name" and "last_name" matches any others, but I want to drop a console.log for every match found. I've thought about using a foreach in a foreach to check element against one another, but that method seems far from elegant.
Is it possible to do this while using the Laravel Unique() method without using nested forEach's?
Example of what I'm currently doing:
$collection->unique(function ($item) {
return $item['first_name'].$item['last_name'];
})->each(function ($item, $key) use ($id) {
// Do stuff..
});
First store duplicates:
$collection = collect([1, 2, 3, 3, 4, 4, 4, 5]);
$duplicates = $collection->duplicates();
Then make your collection unique and store:
$collection = $collection->unique();
Output:
References:
https://laravel.com/docs/9.x/collections#method-duplicates
https://laravel.com/docs/9.x/collections#method-unique
I want to fetch rows from a database, cast them in an array, and then add a custom row so that I can pass the whole thing to a view (Blade file). I've tried using ->push() but I can't seem to get the format of the arrays to match. The below code sample gets rows with the user's id, name, and location.
$profiles = \App\Profiles::orderBy('created_at', 'DESC')->get();
From here, I want to append "distance" to each entry in the collection. I want customized information fetched from the database so that I can pass it seamlessly to a view (Blade file).
You can loop through your array and insert data as below:
$profiles = \App\Profiles::orderBy('created_at', 'DESC')->get();
foreach ($profiles as &$profile) { // loop by reference so it will update current array
$profile->distance = "Your Value";
}
Then you can pass this array to your view. Hope it helps you.
You get a Collection instance, so why don't you use one of its useful methods? In this case Map():
map()
The map method iterates through the collection and passes each value to the given callback. The callback is free to modify the
item and return it, thus forming a new collection of modified items:
$collection = collect([1, 2, 3, 4, 5]);
$multiplied = $collection->map(function ($item, $key) {
return $item * 2;
});
$multiplied->all();
// [2, 4, 6, 8, 10]
So in your case:
$profiles = \App\Profiles::orderBy('created_at', 'DESC')->get();
$profiles->map(function ($profile) {
$profile->distance = 'your value';
return $profile;
});
// Then return it to your view
return view('profiles')->withProfiles('profiles'));
Of course, you can inline all this:
$profiles = \App\Profiles
::orderBy('created_at', 'DESC')
->get()
->map(function($profile) {
$profile->distance = 'your value';
return $profile;
});
// Then return it to your view
return view('profiles')->withProfiles('profiles'));
You said:
I basically want info from the database and my customized info in one
array so that I can pass it easily to a view.
If your desired is to custom/format your data to return it to your view, why noy use Eloquent Resources? Check this section of the documentation.
$profiles is an Eloquent collection, not an array.
$profiles = Profiles::latest()->get();
foreach ($profiles as $profile) {
$profile->distance = 'your value';
}
return view('profile', compact('profiles');
Let's say I have a model collection that I'm mapping through like this:
$alreadyImported = [];
$players = Players::whereNotIn('id', $alreadyImported)
->get()
->random(25)
->pluck('id');
$groups = $players->map(function ($item, $key) use ($alreadyImported) {
array_merge($alreadyImported, $item->id);
$group = [
'username' => $item['username'],
];
return $group;
});
// $groups is a pivot table with group and players
Why does my $globalList always start at []? How can I carry the already-merged $globalList to the next map iteration?
The player IDs does not matter. It's for show. I am looking to pass the array through the map iterations.
Just use pluck() to get IDs from the collection:
$ids = $players->pluck('id');
Or, if you just need IDs:
$ids = Players::where('banned', false)->pluck('id');
If you're going to add any other data, you don't need to merge it to some array or a collection because map() will create a new collection.
Finally, you don't need to use collect() because get() will return collection.
This question already has answers here:
Sorting Laravel Collection via Array of ID's
(3 answers)
Closed last year.
I have an array of ID's as follows:
$ids = [5,6,0,1]
Using Eloquent I am able to search for these Id's using the ->whereIn('id', $ids) function. This as expected will return the results in the ascending order by Id, is there a way I can return the results on the order the array is in? alternatively whats the easiest way to convert the collection in the order of the $ids array?
If there's a specific order you'd like the records in, you'd have to use the Collection Methods:
To get your ID's in the very specific order you've specified, you can make use of the sortBy method as follows, where collection is your collection of models:
$ids = [ 5, 6, 0, 1];
$sorted = $collection->sortBy(function($model) use ($ids) {
return array_search($model->getKey(), $ids);
});
// [ 5, 6, 0, 1] // (desired order)
To randomize your collection you can make use of the shuffle method.
$collection = collect([1, 2, 3, 4, 5]);
$shuffled = $collection->shuffle();
$shuffled->all();
// [3, 2, 5, 1, 4] // (generated randomly)
See the Laravel Docs on shuffle and/or sortBy for more specific requirements.
If you don't really have a specific order in mind, you can use ->inRandomOrder() in version 5.2 and up, older versions would require the raw query using ->orderBy(DB::raw('RAND()')).
See answer to MySQL order by field in Eloquent. It is possible to order the data in your SQL query. Other answers here are suggesting you sort the data after you've already fetched it in "wrong" order.
Your code should look like this:
$ids = [5,6,0,1];
$collection = YourModel::whereIn('id', $ids)
->orderByRaw('FIELD (id, ' . implode(', ', $ids) . ') ASC')
->get();
You can pass a function into the sortBy method to perform complex sorting:
$ids = [5,6,0,1];
$collection = YourModel::whereIn('id', $ids)->sortBy(function($model) use ($ids) {
// Access your array order here and modify the sorting here
});
I have an array ($payments) returned by an Eloquent query with the following JSON encoded output:
[{"id":1, "user_id":"34","amount":"1000","status":"0","created_at":"2016-08-18 14:24:59","updated_at":"2016-08-18 14:24:59"},
{"id":3, "user_id":"33","amount":"300","status":"1","created_at":"2016-08-18 14:31:04","updated_at":"2016-08-18 14:33:20"},
{"id":4, "user_id":"33","amount":"1000","status":"0","created_at":"2016-08-18 14:31:27","updated_at":"2016-08-18 14:31:27"},
{"id":5, "user_id":"34","amount":"400","status":"1","created_at":"2016-08-18 14:42:02","updated_at":"2016-08-18 14:42:02"}]
I want to use the array_where() method in Laravel and filter $payments according this condition : status == 1, could anyone tell me how to do that?
If this is the result of an Eloquent query, it's not an array, it's a Collection. From the documentation:
All multi-result sets returned by Eloquent are an instance of the Illuminate\Database\Eloquent\Collection object
You can use the Collection's filter method, which takes a closure, and return the condition you want ('status' == 1) in the closure.
$filtered = $your_query_result->filter(function($value, $key) {
return $value->status == 1;
});
You may be surprised to find out that there is a php function called array_filter that does exactly that. Here it is in action
$array = [ ['id' => 1, 'status' => 0], ['id' => 2, 'status' => 1], ['id' => 3, 'status' => 0] ];
$array = array_filter($array, function ($item) {
return $item['status'] == 1;
});
Eloquents result cannot be json by default unless You call toJson() method.
Why not just add to Your database query condition?
Example:
$payments = Payment::where('status', '=', 1)->get(); // Payment is model
return response()->json($payments);
p.s. it's not recommended to get a big list of json data from db, parse it and filter it.
make better use of database and don't make Your life hard (: