Introduction
There may be times in your Laravel projects when you want to manually build Collections of data. This might be because you're pulling in data from an external source, such as an API, or because you're generating the data yourself.
Building Collections manually like this can sometimes lead to items of the wrong data type being added to the Collection. For example, you might want to add an integer to a Collection but accidentally add a string instead.
Of course, a good-quality test suite will likely catch these types of problems. But, unfortunately, these types of issues can sometimes slip through the cracks.
So it can be useful to check your Collections to ensure that they contain the correct data types before you start interacting with them.
This is where the ensure() method comes in. In this Quickfire article, we're going to quickly look at how to use the ensure() method to ensure that the items in a Collection are of the correct data type.
Using the ensure() Method
The ensure() method allows you to ensure that the items in a Collection are of a specific data type. If an item in the Collection is not of the specified data type, the method will throw an UnexpectedValueException.
Let's take a look at some examples of how to use the ensure() method.
Checking Primitives
You can use the ensure() method to verify that all the items in a Collection are of these primitive types: string, int, float, bool, or array.
For example, if we wanted to verify that a Collection only contains string items, we could do so like this:
1$collection = collect(['Ash', 'Allen']);2 3$collection->ensure('string');
Similarly, if we wanted to verify that a Collection only contains int items, we could do so like this:
1$collection = collect([1, 2, 3, 4, 5]);2 3$collection->ensure('int');
In the following example, the ensure method will throw an UnexpectedValueException because the Collection contains an int item, but we're trying to ensure that it only contains string items:
1// โ The `ensure` method will throw an exception!2 3$collection = collect([1, 2, 3, 4, 5]);4 5$collection->ensure('string');
The message of the exception thrown will be:
1Collection should only include 'string' items, but 'int' found.
Checking Objects and Interfaces
As well as being able to verify whether a Collection only contains primitive types, you can also use the ensure() method to verify that a Collection only contains objects of a specific class or interface.
For example, if we wanted to verify that a Collection only contains items of the App\Models\User class, we could do so like this:
1use App\Models\User;2 3$collection = collect([4 new User('Ash'),5 new User('Allen'),6]);7 8$collection->ensure(User::class);
In the following example, the ensure method will throw an UnexpectedValueException because the Collection contains a Post object, but we're trying to ensure that it only contains User objects:
1// โ The `ensure` method will throw an exception! 2 3use App\Models\User; 4use App\Models\Post; 5 6$collection = collect([ 7 new User('Ash'), 8 new User('Allen'), 9 new Post(),10]);11 12$collection->ensure(User::class);
We can also use the ensure method to verify that a Collection only contains items that implement a specific interface. For example, if we wanted to verify that a Collection only contains items that implement the Illuminate\Auth\Authenticatable interface, we could do so like this:
1use App\Models\User;2use Illuminate\Auth\Authenticatable;3 4$collection = collect([5 new User('Ash'),6 new User('Allen'),7]);8 9$collection->ensure(Authenticatable::class);
In the above example, we're assuming that the App\Models\User class implements the Illuminate\Auth\Authenticatable interface.
Checking Multiple Types
There may also be times when you want to verify that a Collection contains items of multiple types. You can do this by passing an array of types to the ensure() method.
As long as each item matches at least one of the types in the array, the ensure method will not throw an exception.
For example, if we wanted to verify that a Collection contains items that are either int or float, we could do so like this:
1$collection = collect([1, 2, 3.5, 4, 5]);2 3$collection->ensure(['int', 'float']);
Similarly, if we wanted to verify that a Collection contains items that are instances of either App\Models\User or App\Models\Post, we could do so like this:
1use App\Models\User; 2use App\Models\Post; 3 4$collection = collect([ 5 new User('Ash'), 6 new User('Allen'), 7 new Post(), 8]); 9 10$collection->ensure([User::class, Post::class]);
If you're using the ensure method to check that the Collection contains items of multiple classes, this might be an indication that you should make use of interfaces. So you might want to consider refactoring your classes so they both implement the same interface. This would allow you to use the ensure method to check that the Collection contains items that implement the interface, rather than checking for both of the specific classes.
However, this isn't always possible or needed. It's all dependent on the specific use case.
Using the above approach (passing multiple types to the ensure method) can be really handy if you don't have ownership of the classes in the Collection. For example, the classes might belong to a third-party package, and so it might be difficult (or impossible) to change them to implement the same interface.
In this case, the ensure method can be a useful way to ensure that the Collection contains the correct types of items.
Things to Note
It's important to note that the ensure method will only verify the items that are already in the Collection. If you add any more items to the Collection after calling the ensure method, it won't stop you from adding the wrong type of item to the Collection.
For this reason, if you're going to run the ensure method, you may want to consider running it only once you've finished adding items to the Collection.
Additionally, it's best to use the ensure method as a last resort fallback to catch any errors that might have slipped through the cracks. In a perfect world, you never want this method to throw an exception.
So, while the ensure method can be a useful tool, it's not a replacement for a good quality code and a thorough test suite.
Making proper use of type hinting, return types, and strict type-checking can help to avoid adding the incorrect data to the Collection in the first place.
Conclusion
Hopefully, this article has given you a quick insight into the ensure() method.
You might also be interested in checking out my 220+ page ebook "Battle Ready Laravel" which covers similar topics in more depth.
Or, you might want to check out my other 440+ ebook "Consuming APIs in Laravel" which teaches you how to use Laravel to consume APIs from other services.
If you're interested in getting updated each time I publish a new post, feel free to sign up for my newsletter below.
Keep on building awesome stuff! ๐