DEV Community

loading...

Laravel Collections Higher Order Messages - Single Line Magic

ppshobi profile image Shobi ・1 min read

Collections are wrappers around arrays in PHP. Collections provide fluent interfaces and intuitive APIs to access arrays. Laravel comes with collections out of the box, and Laravel's eloquent ORM returns the result set in the form of collections by default.

Collections come with many useful methods which allow us to easily manipulate arrays, and they are chainable as well. Compared to the built-in PHP array manipulation functions, collections offers much readable and consistent syntax.

Here I will show you a little refactoring technique you can do while tinkering with collections using higher order messages.

Collections provide support for "higher order messages", which are short-cuts for performing common actions on collections. Documentation

Consider the scenario where you need to map over a collection and call method on the item

<?php
User.php
--------- 

/** 
 * the method returns the full name of the user 
 * by joining first and last name 
**/

function fullName(){
   return $this->first_name . ' ' . $this->last_name;
}

SomeFile.php
------------
/** 
 * In some other file, we need full names of all users 
**/

$fullNames = User::all()->map(function ($user) {
    return $user->fullName()
});

the above code shows how we do it normally with map(), but functions with the simple body as in the above code, we can use higher-order functions to cut the explicit crap.

<?php
$fullNames = User::all()->map->fullName();

Boom ⚡ Single line Magic 🔥❤️

Let's goto a little more complex scenario where we need to filter over a collection and then map over them again

<?php

User.php
---------
/** 
 * the method returns the full name of the user by joining first and last name 
**/

public function fullName() {
   return $this->first_name . ' ' . $this->last_name;
}

/** 
 * the method returns the if the first_name starts with a given letter 
**/

public function isStartingWith($letter) {
    return starts_with($this->first_name, $letter)
}

OtherFile.php
-------------
/** 
 * In some file, we need full names of all users which starts with 'A'
**/

$fullNamesWithA = User::all()->filter(function($user){
    return $user->isStartingWith('A');
})->map(function ($user) {
    return $user->fullName()
});

Let's try to use Collection Higher-order functions here and cut explicit syntax crap.

<?php
$fullNamesWithA = User::all()->filter->isStartingWith('A')->map->fullName();

Boom ⚡ Single line Magic 🔥❤️ Again

Adiós

Discussion (6)

pic
Editor guide
Collapse
govtvacancyjobs profile image
Collapse
khalyomede profile image
Khalyomede

Very fluent!! Is this compatible with all Laravel versions?

Collapse
ppshobi profile image
Shobi Author

I think by Laravel, 5.4, this feature got introduced

Collapse
mattmangoni profile image
Matteo Mangoni

It's a nice feature, but it makes reading your code slightly harder.
It may seem like a good idea now, but your future self or your teammates may disagree.

Collapse
ppshobi profile image
Shobi Author

I should disagree with you here ;), as a developer when you write multiple nested ternary operators for a complex if conditional, I can understand that it reduces the readability, whereas when you write a ternary instead of a simple if condition in one line, rather I'd appreciate you,

Collapse
mattmangoni profile image
Matteo Mangoni

Maybe I just need to get used to it :)