Collection Classes in PHP

Share this article

A Collection class is an OOP replacement for the traditional array data structure. Much like an array, a collection contains member elements, although these tend to be objects rather than simpler types such as strings and integers. The general characteristics of a collection class are:

  • Establishes a wrapper around a array of objects.
  • Collections are mutable – new elements may be added and existing elements may be modified or removed.
  • Sorting algorithms are unstable (which means the order for equal elements is undefined).
  • Can use lazy instantiation to save system resources.

Problem with Arrays

Applications frequently have objects that contain a group of other objects, and this is a great place to make use of collections. For example, suppose we decide to create a book store system. Let’s say we’ve written a customer class which, among other things, holds a list of books that the customer would like to purchase:
<?php
class Customer 
{
    public $items = array();
    // ...
}

$customer = new Customer(1234);
foreach ($customer->items as $item) {
    echo $item->name;
}
If the most obvious approach (using an array) were the best possible approach, I wouldn’t write this article. The above example has these problems:
  • We’ve broken encapsulation – the array is exposed as a public member variable.
  • There is ambiguity in indexing and how to traverse the array to find a specific item.
Additionally, to make sure the array is available for any code that might access it, we must populate the list of information from the database at the same time as the customer information. This means that even if we want to print just the customer’s name, we must fetch all of the item information, unnecessarily increasing load on the database and potentially bogging down the entire application. We can solve those problems by creating a collection class as an OOP wrapper around the array and use lazy instantiation. Lazy instantiation is the mechanism by which we create elements in the array only when we actually need it. It’s called “lazy” because the object determines on its own when to instantiate the component objects rather that blindly creating them when it is instantiated.

A Basic Collection Class

A collection class needs to expose methods that allow us to add, retrieve, and delete items, and it’s helpful to have a method that lets us know the size of the collection. So, a basic class would start like this:
<?php
class Collection 
{
    private $items = array();

    public function addItem($obj, $key = null) {
    }

    public function deleteItem($key) {
    }

    public function getItem($key) {
    }
}
The $items array provides a location in which to store the objects that are members of the collection. addItem() lets us add a new object to the collection, deleteItem() removes an object, and getItem() returns an object. With addItem(), we add an object to the collection by putting it in the $items
array at a specified location specified by $key (if no key is provided, we let PHP pick the next available index). If an attempt is made to add an object using a key that already exists, an exception should be thrown to prevent inadvertently overwriting existing information:
public function addItem($obj, $key = null) {
    if ($key == null) {
        $this->items[] = $obj;
    }
    else {
        if (isset($this->items[$key])) {
            throw new KeyHasUseException("Key $key already in use.");
        }
        else {
            $this->items[$key] = $obj;
        }
    }
}
The deleteItem() and getItem() methods take the key as a parameter indicating which items are targeted for removal or retrieval. An exception should be thrown if an invalid key is supplied.
public function deleteItem($key) {
    if (isset($this->items[$key])) {
        unset($this- >items[$key]);
    }
    else {
        throw new KeyInvalidException("Invalid key $key.");
    }
}

public function getItem($key) {
    if (isset($this->items[$key])) {
        return $this->items[$key];
    }
    else {
        throw new KeyInvalidException("Invalid key $key.");
    }
}
Because the $key parameter to the addItem() method is optional, we won’t necessarily know the key used for each item in the collection. Adding a method that can provide a list of keys to any external code that might need it is a good idea. The keys can be returned as an array:
public function keys() {
    return array_keys($this->items);
}
It might also be helpful to know how many items are in the collection.
public function length() {
    return count($this->items);
}
And because getItem() and deleteItem() can throw an exception if an invalid key is passed, a means of determining whether a given key exists in the collection is also a good idea.
public function keyExists($key) {
    return isset($this->items[$key]);
}
To use the Collection
class as it stands now, create the file Collection.php and save the code for the Collection class in it. Create files for the KeyInvalidException and KeyhasUseException classes, too (they can be simple sub-classes of the base Exception class). Be sure to add require statements if you’re not using an autoloader, and then try the following test code:
<?php
require_once "Collection.php";

class Salut
{
    private $name;
    private $number;

    public function __construct($name, $number) {
        $this->name = $name;
        $this->number = $number;
    }

    public function __toString() {
        return $this->name . " is number " . $this->number;
    }
}

$c = new Collection();
$c->addItem(new Salut("Steve", 14), "steve");
$c->addItem(new Salut("Ed", 37), "ed");
$c->addItem(new Salut("Bob", 49), "bob");

$c->deleteItem("steve");

try {
    $c->getItem("steve");
}
catch (KeyInvalidException $e) {
    print "The collection doesn't contain Steve.";
}
This example may not be particularly interesting, but it should give you an idea of how the class is used.

Conclusion

Collections can be seen as more-specialized way of working with lists for which certain contracts are guaranteed. A Collection class is a very useful OO alternative to the traditional array, and one that can be implemented in virtually any application you might build. It provides careful management of its members and a consistent API that makes it easy to write code that uses the class.

Frequently Asked Questions (FAQs) about Collection Classes in PHP

What are the benefits of using collection classes in PHP?

Collection classes in PHP provide a more efficient way to handle data sets. They offer a structured, object-oriented approach to managing data, which can improve code readability and maintainability. Collection classes also provide a wide range of built-in methods for manipulating data, such as sorting, filtering, and mapping. This can save developers time and effort as they don’t need to write these functions from scratch. Additionally, collection classes can enhance performance, especially when dealing with large data sets, as they are optimized for efficient data handling.

How do I create a collection class in PHP?

Creating a collection class in PHP involves defining a class that encapsulates a group of objects. This class should include methods for adding, removing, and retrieving items from the collection. Here’s a basic example:

class Collection
{
protected $items = [];

public function add($item)
{
$this->items[] = $item;
}

public function remove($item)
{
$index = array_search($item, $this->items);
if ($index !== false) {
unset($this->items[$index]);
}
}

public function getItems()
{
return $this->items;
}
}

How can I use Laravel collections?

Laravel collections provide a convenient, fluent interface for dealing with arrays of data. You can create a collection by using the collect helper function, like so:

$collection = collect([1, 2, 3, 4, 5]);

Once you have a collection, you can use various methods to manipulate the data. For example, you can use the map method to apply a function to each item in the collection:

$collection->map(function ($item, $key) {
return $item * 2;
});

What is the DS\Collection class in PHP?

The DS\Collection class is part of the PHP Data Structures extension (DS). It provides an interface that all the data structures in the DS extension adhere to. This means you can use the same methods to manipulate different types of data structures, such as stacks, queues, and vectors. However, please note that the DS extension is not included in PHP by default and needs to be installed separately.

How can I filter data in a collection?

Most collection classes provide a filter method that allows you to remove items from the collection based on a callback function. Here’s an example:

$collection = collect([1, 2, 3, 4, 5]);
$filtered = $collection->filter(function ($value, $key) {
return $value > 2;
});

In this example, the filter method will remove any items from the collection that do not pass the provided test (in this case, values that are less than or equal to 2).

Can I use collection classes with databases in PHP?

Yes, collection classes can be very useful when working with databases in PHP. For example, Laravel’s Eloquent ORM returns query results as collection instances, allowing you to use collection methods to manipulate the data. This can make your code more readable and maintainable.

How can I sort data in a collection?

Most collection classes provide a sort method that allows you to sort the items in the collection. You can provide a callback function to determine the sort order. Here’s an example:

$collection = collect([5, 3, 1, 4, 2]);
$sorted = $collection->sort();

In this example, the sort method will sort the items in ascending order.

What is the difference between arrays and collection classes in PHP?

While both arrays and collection classes can be used to store and manipulate data, there are some key differences. Collection classes are object-oriented and provide a wide range of built-in methods for manipulating data, which can make your code more readable and maintainable. On the other hand, arrays in PHP are basic data structures with a limited set of functions for data manipulation.

Can I convert a collection to an array?

Yes, most collection classes provide a method to convert the collection to an array. For example, in Laravel, you can use the toArray method:

$collection = collect([1, 2, 3, 4, 5]);
$array = $collection->toArray();

How can I iterate over a collection?

You can iterate over a collection in much the same way as you would an array, using a foreach loop. Most collection classes also provide methods for iterating over the items in the collection, such as each, map, and filter. Here’s an example:

$collection = collect([1, 2, 3, 4, 5]);
$collection->each(function ($item, $key) {
echo $item;
});

In this example, the each method will execute the provided callback for each item in the collection.

Alireza Rahmani KhaliliAlireza Rahmani Khalili
View Author

To whom it may concern, I'm Alireza. For a significant chunk of my waking hours I’m a PHP expert, Author, Speaker and independent consultant on the design of enterprise web applications with Master's degrees in Computer Science. I <3 Tech, But pass time away from computers as an aspiring amateur writer, fishing, traveling, hunting, soccer- I'm a massive Liverpool FC fan!

Intermediate
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week