April 14, 2017

Using Laravel Collections in Drupal

Written by Matt Williams @mwilliamsdev

Share on LinkedIn

If you’re a developer used to the Laravel framework and find yourself working on a Drupal project, you may miss the ease of fluently mapping and reducing your data without having to remember which order the parameters go in (looking at you array_map() and array_reduce()). Luckily the handy little Collect package will let you bring the power of Collections to Drupal!

For those unfamiliar, the Collection class in Laravel provides convenient, chainable methods for working with arrays of data. There is a long list of available methods from functional favorites like map(), filter(), and reduce() to handy math shortcuts like sum(), median(), and average(). Check out the full list of methods and read more about them in the Laravel documentation.

Since Drupal 8 uses Composer to manage dependencies, adding the Collect package is the same as adding any other package. Simply run:

composer require tightenco/collect

Adding Collections to Drupal 7 requires a little more work, since Drupal 7 doesn’t use PSR-4 namespaces and autoloading. We can get around this by using to the module Composer Manager, which will allow your custom modules to depend on PHP libraries managed via Composer. After downloading & enabling the Composer Manager module you’ll want to go to the configuration at /admin/config/system/composer-manager/settings and adjust the options to fit environment.

Next add a composer.json file to a custom module’s root directory with the following:

{
  "require": {
    "tightenco/collect": "^5.4"
  }
}

Enable your custom module if it isn’t already using:

drush en CUSTOM_MODULE_NAME

You should see Composer install the dependencies in addition to your module being enabled. If your module is already enabled, you can instead run:

drush composer install

If the package was successfully added, you should see it listed under /admin/config/system/composer-manager.

We can now start using the Collection class in our module! At the top of your module file require the class with:

use Illuminate\Support\Collection;

From here you can turn any Array into a Collection using the simple, aptly named helper method collect(). Here’s a basic example showing how we might write a simple method using a Collection instead of an Array:

function _get_product_credit_total_from_order($order) {
  $total = 0;
  $credit_types = ['bonus_product_credit','defective_product_credit'];

  foreach ($order->line_items as $item) {
    if(in_array($item['type'], $credit_types)) {
      $total += $item['amount'];
    }
  }

  return $total;
}

Can alternatively be written as:

function _get_product_credit_total_from_order($order) {
  $credit_types = ['bonus_product_credit','defective_product_credit'];

  return collect($order->line_items)
    ->whereIn('type', $credit_types)
    ->sum('amount'); 
}

Pretty nifty huh? Explore the documentation and see if you change the way you work with arrays!

We'd love to chat about your next web or application project!