DEV Community

Cover image for Using Collections package outside of Laravel
Roberto B.
Roberto B.

Posted on

Using Collections package outside of Laravel

If you used Laravel, probably you know and used the powerful Collection class.

The Collection class (Illuminate\Support\Collection) is included in the Illuminate Collections package illuminate/collections

Collection class is useful when you need to work with collections of data, and you need some additional powerful method.

The Illuminate\Support\Collection class provides a fluent, convenient wrapper for working with arrays of data.

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 Collection class?
Sometimes I used Collection instead of PHP array:

  • when I need a superset of additional functions: https://laravel.com/docs/9.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

Let me start with 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": "^9.0"
    }
}
Enter fullscreen mode Exit fullscreen mode

One important thing to know is that Illuminate Collections 9 requires PHP 8 (version greater than 8.0.2).

The dependencies of Illuminate Collections 9 (9.0.2) are:

illuminate/collections   v9.0.2 The Illuminate Collections package.
illuminate/conditionable v9.0.2 The Illuminate Conditionable package.
illuminate/contracts     v9.0.2 The Illuminate Contracts package.
illuminate/macroable     v9.0.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), you could consider using the previous version of the package, the version 8.

PHP Version Collections Version
7.4 8
8.0 9
8.1 9

My strong suggestion is to use an updated stack, so PHP 8.x and Illuminate Collections 9.

To install a previous version of Illuminate Collections package:

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

Use Collection class

Once you have installed the package, you can start using the class, let's see 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()".

You can also create a specific 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

Discussion (0)