Introduction
If you use Laravel, chances are, you probably use Collections on a daily basis. As described on the Laravel website, a Collection is a class that "provides a fluent, convenient wrapper for working with arrays of data". They can be extremely useful and when used properly, they can make things like array iteration and manipulation (adding/removing/updating items) much nicer to work with and to read.
If you aren't familiar with Collections, I'd strongly suggest reading about them on the official Laravel documentation here.
How to use the whereInstanceOf() method
One method that I have found particularly useful recently when working on a project was the whereInstanceOf()
method. Without going into too much details (and boring you with the business logic), I needed to the filter a Collection based on a class type. The Collection contained items that were of 3 different types of models (Post
, Video
, Image
).
To show you how I filtered the Collection, here's an extremely simplified example below. The $this->getItems()
method performs some queries and logic that returns a Collection of posts, videos and images.
1use App\Models\Post;2use App\Models\Video;3use App\Models\Image;4 5/** @var Collection */6$collection = $this->getItems();7 8$posts = $collection->whereInstanceOf(Post::class);
In the example above, the $posts
variable will now be a Collection that only contains Post
models.
Filtering on multiple classes
As you can imagine, using this filter can be really useful sometimes. But there may also be times when you want to filter the collection using more than one class.
For instance, in my example above, I might need to filter the Collection so that I can get all the videos and images. Before Laravel 8.29, you would have had to use the filter
method, like seen in the example below:
1use App\Models\Post; 2use App\Models\Video; 3use App\Models\Image; 4 5/** @var Collection */ 6$collection = $this->getItems(); 7 8$videosAndImages = $collection->filter(function ($value) { 9 if ($value instanceof Video::class || $value instanceof Image::class) {10 return true;11 }12 13 return false;14});
Although this code works and is fairly clean, it could still be simplified further to make reading it even easier.
So, I made a pull request to add the functionality to the laravel/framework
repository on GitHub to try and extend the Collection's functionality for filtering based on multiple classes.
Now, as of Laravel 8.29, you can pass in either a string or an array to the whereInstanceOf()
method.
To see how we could update our example above to use the functionality, we could update our code to this:
1use App\Models\Post;2use App\Models\Video;3use App\Models\Image;4 5/** @var Collection */6$collection = $this->getItems();7 8$videosAndImages = $collection->whereInstanceOf([Video::class, Image::class]);
As I'm sure that you'll agree, this looks much cleaner to read and interpret than the previous example. Small syntactical sugar changes like these (in my opinion) are always nice because it helps to make your code simple and enjoyable to work with.
If you've used this functionality in your own project, I'd love to hear about it in the comments!