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```php

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 ```php 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 ```php 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 ```php [ '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.