DEV Community

Cover image for Empowering PHP Arrays: The Magic of Laravel Collections Revealed
Roberto B.
Roberto B.

Posted on • Updated on

Empowering PHP Arrays: The Magic of Laravel Collections Revealed

If you've worked with Laravel, chances are you're familiar with the powerful Collection class.

The Collection class (Illuminate\Support\Collection) is an integral part of the Illuminate Collections package, which can be found at illuminate/collections.

The Illuminate\Support\Collection class proves invaluable when dealing with data collections, offering a range of powerful methods to enhance your workflow.

The Illuminate\Support\Collection offers a seamless and convenient interface for handling data arrays, enhancing code readability and expressiveness.

PHP has a lot of functions to manage arrays. The PHP official documentation for array functions is: https://www.php.net/manual/en/ref.array.php

So, why would you need the Collection class?
There are several scenarios where using Collection instead of a PHP array is advantageous:

  • when I need a superset of additional functions: https://laravel.com/docs/10.x/collections#available-methods;
  • I want to chain methods to perform fluent mapping and reducing of the underlying array;
  • because collections are immutable, meaning every Collection method returns an entirely new Collection instance;
  • because collections are "macroable", which allows you to add additional methods to the Collection class at run time.

If I'm working on a PHP project without Laravel Framework, can I use Collection class? The answer is YES 🥳🥳🥳

Install illuminate/collections package

Begin by creating a new PHP project from scratch using Composer

mkdir test-collections
cd test-collections
composer require illuminate/collections
Enter fullscreen mode Exit fullscreen mode

The composer command generates the composer.json file. If you open it:

{
    "require": {
        "illuminate/collections": "^10.34"
    }
}
Enter fullscreen mode Exit fullscreen mode

One important thing to know is that Illuminate Collections 10 requires PHP 8.1.

The dependencies of Illuminate Collections 10 are:

illuminate/collections   v10.34.2 The Illuminate Collections package.
illuminate/conditionable v10.34.2 The Illuminate Conditionable package.
illuminate/contracts     v10.34.2 The Illuminate Contracts package.
illuminate/macroable     v10.34.2 The Illuminate Macroable package.
psr/container            2.0.2    Common Container Interface (PHP FIG PSR-11)
psr/simple-cache         3.0.0    Common interfaces for simple caching
Enter fullscreen mode Exit fullscreen mode

If you can't use PHP 8 for any reason (for example, if you are using PHP 7.4), consider using the previous version of the package, version 8.

PHP Version Collections Version
7.4 8
8.0 9
8.1 9 or 10
8.2 10
8.3 10

I strongly suggest using an updated stack, such as PHP 8.3 (or PHP 8.2) and Illuminate Collections 10.

To install a previous version of the Illuminate Collections package:

composer require illuminate/collections:9.x
Enter fullscreen mode Exit fullscreen mode

Use Collection class

After successfully installing the package, you can begin utilizing the class. Here's how:

<?php

require "vendor/autoload.php";

use Illuminate\Support\Collection;

$fruits = new Collection(['🥑', '🍒', '🍎', '🍌']);
print_r($fruits->all());
/*
Array
(
    [0] => 🥑
    [1] => 🍒
    [2] => 🍎
    [3] => 🍌
)
*/
Enter fullscreen mode Exit fullscreen mode

You can:

  • require the autoload file;
  • import (via use keyword) Illuminate\Support\Collection;
  • instance the Object from Collection class;
  • use a method like all() from Collection class.

For instancing Collection object, you can use new or calling the static method make:

$fruits = Collection::make(['🥑', '🍒', '🍎', '🍌']);
print_r($fruits->all());
Enter fullscreen mode Exit fullscreen mode

2 examples, same result. Under the hood, make it call and returns "new Collection()".

Additionally, you can create a custom macro, so you can add the new method at runtime to Collection object

<?php

require "vendor/autoload.php";
use Illuminate\Support\Collection;

Collection::macro('blend', function () {
    return $this->map(function ($value) {
        return mb_chr(mb_ord($value) + 1);
    });
});
$fruits = Collection::make(['🥑', '🍒', '🍎', '🍌']);
$newFruits = $fruits->blend();
print_r($newFruits->all());
/*
Array
(
    [0] => 🥒
    [1] => 🍓
    [2] => 🍏
    [3] => 🍍
)
*/
Enter fullscreen mode Exit fullscreen mode

Collection with nested data

You can create collections with structure data (not just flat array):

$collection = Collection::make([
    "avocado" =>
        [
            'name' => 'Avocado',
            'fruit' => '🥑',
            'wikipedia' => 'https://en.wikipedia.org/wiki/Avocado'
        ],
    "apple" =>
        [
            'name' => 'Apple',
            'fruit' => '🍎',
            'wikipedia' => 'https://en.wikipedia.org/wiki/Apple'
        ],
    "banana" =>
        [
            'name' => 'Banana',
            'fruit' => '🍌',
            'wikipedia' => 'https://en.wikipedia.org/wiki/Banana'
        ],
    "cherry" =>
        [
            'name' => 'Cherry',
            'fruit' => '🍒',
            'wikipedia' => 'https://en.wikipedia.org/wiki/Cherry'
        ],
]);

$filtered = $collection->whereIn('name', ['Apple', 'Banana']);

$some = $filtered->all();
print_r($some);
/*
Array
(
    [apple] => Array
        (
            [name] => Apple
            [fruit] => 🍎
            [wikipedia] => https://en.wikipedia.org/wiki/Apple
        )

    [banana] => Array
        (
            [name] => Banana
            [fruit] => 🍌
            [wikipedia] => https://en.wikipedia.org/wiki/Banana
        )

)
*/
Enter fullscreen mode Exit fullscreen mode

Chain methods: filtering and selecting columns

You can chain methods and custom (macro) methods.
The scenario is: you want to filter (whereBetween) and select some columns (select macro)

Collection::macro('select', function (array $fields) {
    return $this->map(function ($value, $key) use ($fields) {
        $columns = [];
        foreach ($fields as $field) {
            $columns[$field] = $value[$field];
        }
        return $columns;
    });
});

$select = $collection
    ->select(['fruit', 'name'])
    ->whereBetween('name', ['A', 'B']);
print_r($select->all());
/*
(
    [avocado] => Array
        (
            [fruit] => 🥑
            [name] => Avocado
        )

    [apple] => Array
        (
            [fruit] => 🍎
            [name] => Apple
        )

)
*/
Enter fullscreen mode Exit fullscreen mode

References

Top comments (0)