We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Laravel Collections are a powerful feature that allow developers to work with arrays and other data structures in an intuitive, object-oriented way. They provide a clean, expressive API to manipulate data without the need to loop through arrays manually. One of the many ways to extend the functionality of Laravel collections is through macros, which allow you to define custom methods that can be reused throughout your application.
In this blog post, we'll take a closer look at a custom macro that performs recursive mapping on arrays and objects within a collection.
Understanding the code
Here's the macro in question:
Collection::macro('recursive', function () {
return $this->map(function ($value) {
if (is_array($value)) {
return collect($value)->recursive();
}
if (is_object($value)) {
return collect((array) $value)->recursive();
}
return $value;
});
});
This macro extends Laravel's Collection
class with a new method named recursive
. The goal of this method is to
recursively map over arrays and objects within a collection, transforming all nested structures into collections
themselves.
Let's break it down step by step.
Defining the macro
Collection::macro('recursive', function () {
Macros in Laravel allow you to add custom methods to existing classes. Here, we're adding a method called recursive
to
the Collection
class. By using the macro()
method, we can inject this functionality anywhere in our Laravel
application.
Mapping the collection
return $this->map(function ($value) {
Inside the macro, the first operation is to call the map()
method on the current collection ($this
). The map()
function iterates over each item in the collection and allows you to transform it.
The anonymous function passed to map()
will receive each element ($value
) in the collection. Depending on what type
of data $value
contains, we'll handle it differently.
Handling arrays
if (is_array($value)) {
return collect($value)->recursive();
}
If the current item is an array, we convert it into a collection using the collect()
helper. This converts the array
into a Laravel collection, and we call the recursive()
method on it to ensure that any nested arrays or objects within
it are also recursively transformed into collections.
Handling objects
if (is_object($value)) {
return collect((array) $value)->recursive();
}
Similarly, if the item is an object, we first cast it into an array using (array) $value
, then wrap that array into a
collection with collect()
. As with arrays, the recursive()
method is called to ensure that any nested structures are
handled.
Returning primitive values
return $value;
Finally, if the value is neither an array nor an object (for example, if it's a string, integer, boolean, etc.), we simply return it as is.
Why use a recursive collection macro?
There are several scenarios in which a recursive collection might be useful:
-
Working with deeply nested data: APIs or database queries might return complex, deeply nested arrays or objects. By converting everything into collections, you gain access to Laravel's powerful collection methods, such as
filter()
,pluck()
, andeach()
, on every level of the data structure. -
Consistent Data Structures: When working with a mix of arrays and objects, it can be cumbersome to constantly check and convert data types. By recursively converting everything to collections, you ensure consistency across your data handling.
-
Cleaner Code: Collections provide a fluent, expressive syntax that can make your code easier to read and maintain compared to manually looping through data and checking types.
Example usage
Let's take a look at how you might use this macro in a real-world scenario:
$data = [
'user' => [
'name' => 'John Doe',
'roles' => [
['id' => 1, 'name' => 'Admin'],
['id' => 2, 'name' => 'Editor']
]
],
'settings' => (object) [
'theme' => 'dark',
'notifications' => [
'email' => true,
'sms' => false
]
]
];
$collection = collect($data)->recursive();
// Now you can work with the entire structure as collections
$adminRole = $collection->get('user')->get('roles')->firstWhere('id', 1);
$theme = $collection->get('settings')->get('theme');
In this example, the $data
array contains a mix of nested arrays and objects. By calling recursive()
, we can treat
everything as collections and use collection methods like firstWhere()
and get()
to work with the data in a clean,
readable way.
Conclusion
Extending Laravel's collections with a recursive macro is a great way to simplify working with complex, nested data structures. It allows you to leverage the full power of Laravel's collection API, even with deeply nested arrays and objects, without the need for manual loops or conditionals.
By using this macro, your code becomes more expressive, consistent, and maintainable. If you regularly work with nested data in Laravel, this is a trick worth adding to your toolbox.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.