You've worked with APIs, right? You make a request, you get some data back, and you do something with it. Pretty standard stuff. This tutorial will show you how you can use the power of PHP collections to easily get the data you want.
What are PHP collections? Simply put: a collection is a class that allows us to easily work with arrays.
For this tutorial, we'll be using the tightenco/collect
package. This package allows us to use Laravel Collections without the entire framework.
A Collections-only split from Laravel's Illuminate Support
Collect - Illuminate Collections
Import Laravel's Collections into non-Laravel packages easily, without needing to require the entire Illuminate\Support
package. (Why not pull Illuminate\Support
in framework-agnostic packages)
Written by Taylor Otwell as a part of Laravel's Illuminate/Support package, Collect is just the code from Support needed in order to use Collections on their own.
Lovingly split by Matt Stauffer for Tighten Co., with a kick in the butt to finally do it from @assertchris.
Installation
With Composer:
composer require tightenco/collect
Development
If you are a developer working on Collect and you're tasked with upgrading it to mirror a new version of Laravel, run ./upgrade.sh
from the root directory. You can pass a parameter to target a specific Laravel version (e.g. ./upgrade.sh 5.7.10
) or, if you don't pass a parameter, the script will find the latest tagged release and run against that.
The upgrader will pullβ¦
Data for this tutorial was provided by the OMDb API.
Rather than embed the data, you can view it here.
A Simple Example
Before we get into parsing our movie data, let's do a quick example. In this example, we'll grab the first and last item in an array.
use Tightenco\Collect\Support\Collection;
$simpsons = ['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie'];
$c = new Collection($simpsons);
echo $c->first(); // Homer
echo $c->last(); // Maggie
Pretty easy, right? We have an array which we use to make a new Collection
instance. From there we use the first()
and last()
methods to grab "Homer" and "Maggie."
Getting Started
First, we need to first use Composer to pull in our Collection package.
composer require tightenco/collect
Now for each example, we need to include our dependencies and do a little setup.
<?php
require 'vendor/autoload.php';
use Tightenco\Collect\Support\Collection;
$json = file_get_contents(__DIR__ . '/data.json');
$movies = json_decode($json, true);
$c = new Collection($movies);
Collection Methods
The Collection
package provides us with a ton of great methods we can use to manipulate our data. Since there are ~110 methods, I won't be going over each one. Instead, I'll highlight a few and explain their functionality.
.map()
The map()
function loops through the data and passes each item to the given callback. You are then able to return the item to create a new collection. Below we'll create a new collection that contains only each film's title.
$titles = $c->map(function ($movie) {
return $movie['Title'];
});
Result:
['The Matrix', 'Blade Runner', 'The Fifth Element', 'Escape From New York']
You're not limited to just returning a single value. Let's create a collection that includes each film along with the date of release.
$release = $c->map(function ($movie) {
return [$movie['Title'] => [
'releaseDate' => $movie['Released']
]];
});
Result:
[
'The Matrix' => ['releaseDate' => '31 Mar 1999'],
'Blade Runner' => ['releaseDate' => '25 Jun 1982'],
'The Fifth Element' => ['releaseDate' => '09 May 1997'],
'Escape From New York' => ['releaseDate' => '10 Jul 1981']
]
Now, let's format the date.
$release = $c->map(function ($movie) {
return [$movie['Title'] => [
'releaseDate' => date('F d, Y', strtotime($movie['Released']))
]];
});
Result:
[
'The Matrix' => ['releaseDate' => 'March 31, 1999'],
'Blade Runner' => ['releaseDate' => 'June 25, 1982'],
'The Fifth Element' => ['releaseDate' => 'May 09, 1997'],
'Escape From New York' => ['releaseDate' => 'July 10, 1981']
]
Side note: if this were a real project I would probably use PHP's DateTime or Carbon to format the date.
.filter()
The filter()
method, well, filters the data. Any items that pass a given test will be returned. In the example below, we return any movie whose "Metascore" is at least 70.
$metascore = $c->filter(function ($movie) {
return $movie['Metascore'] >= 70;
});
Result:
[
[
'Title' => 'The Matrix'
...
],
[
'Title' => 'Blade Runner'
...
],
[
'Title' => 'Escape From New York'
...
]
]
.sum()
The .sum()
method is handy when you want to total values. In this example, I use the map()
method to return each movie's runtime and then total them to see how long it would take to watch all four films.
$runtime = $c->map(function ($movie) {
/**
* Breakdown:
*
* 1. Remove " min" from the string.
* 2. Cast the string to an integer so we can add them
*/
return (int) str_replace(' min', '', $movie['Runtime']);
})->sum();
Result:
.count()
Like .sum()
, .count()
is a very simple method that can really come in handy when you want to know how many items are in your collection.
Further Reading
There are ~106 other methods available with this specific package. I encourage you to read the documentation.
Laravel's Collection package isn't the only game in town. Doctrine has a great one and there are many others availble, too! Go find one you like!
Also, Adam Wathan has a great book called Refactoring to Collections that I highly recommend.
[Full disclosure, I'm not being compensated in any way for linking to this book. I just think it's great. That said, Adam, if you're reading this and would like me to become a paid endorser, just get in touch π]