Playing
01. Custom Laravel Collections

Episodes

0%
Your progress
  • Total: 15m
  • Played: 0m
  • Remaining: 15m
Join or sign in to track your progress

Transcript

00:00
Okay. So in this snippet, we are going to take a look at how we can create custom Laravel collections for our models. And really the point of this is to nicely clean up code and just make it a little bit
00:12
more efficient when you are writing code. So we're specifically going to look at two examples here. The first one is going to be a batch of notifications, what happens if we want to mark all of them red in one go.
00:24
And the second one is going to be slightly different. This is going to involve user settings and how we can conveniently access keys for user settings. So two really useful things that you can go ahead and implement in your own project straight
00:37
away. So the first thing that we're going to do, I have a fresh Laravel installation over here. I'm going to go ahead and just migrate the user migrations that are by default in here. So we have them in there.
00:49
And of course, we're going to go ahead and create some kind of model. So let's create a notification model. Let's create a migration and a factory alongside of that as well. And let's just really quickly do this because we're not worried too much about the implementation
01:01
details here. So in the table for this, we're going to go ahead and create a reference to the user ID. And let's just make that unsigned and an index. And let's go down and just create something that we want to mass update based on the user's
01:15
notifications. And we'll see an example of the code in just a second if this doesn't make sense. But something like a red update. So if you've used Laravel notifications before, you'll know that this is pretty much what
01:27
they do. So let's go ahead and make this nullable because, of course, we don't want this to be always red. And let's set a default on this of null, so that's put in there when we create this.
01:37
Okay, so let's go ahead and run our migrations again. That will have gone ahead and created them. And if we just head over to our user model and set up this relationship very quickly, we'll take a look at an example of the two ways that we can do this.
01:51
So let's go ahead and say that a user has many notifications. So let's reference that model. And we should be just about good to go. Okay, so if we head over to routes and web, let's go ahead and fetch out a user in here.
02:05
I don't actually have one created at the moment. But I'm going to go ahead and do that with Tinker. And I'm just going to find the user with an ID of one. Okay, so let's head over to the command line and run PHP artisan Tinker.
02:17
And let's go and say factory app user. And let's go ahead and create a user. So that will be a user ID of one, like so. And let's go ahead and do the same thing, but this time for the notification.
02:33
And we'll assign this to that particular user. So we'll create a few users in here. So just playing around with this. So let's create one, two, and three.
02:42
So if we head over to our database, over to notifications, Red Hat is set to null. And the way that we would normally do this is go ahead and we just die dump first on user notifications, just to make sure that we're getting them through. You'll see the following.
02:57
So of course, got a collection of three items here. And normally, what we would do if we wanted to mark all of these notifications red, we would say user notifications, and then each. So that's just a collection method, which allows us to create a function inside of here.
03:13
And then for each of the iterations of this, we get a notification through. And we can say something like notification, and then mark red. So if we just head over to our notification model, and let's go ahead and create out the fillable fields in here, first of all.
03:30
So let's say that Red Hat is fillable. Let's also go ahead and set the dates in here. So these are represented by carbon instances. So we've got Red Hat, and let's introduce that helper method, which makes our code look
03:43
a little bit better already, which is mark red. And let's go ahead and just say this update, and set Red Hat in here, too. And we can use the Laravel now helper function, which just returns to us a carbon instance. So now that we've done that, and we're iterating through each of these notifications, of course,
04:06
what we can do is head over here and give that a refresh. And sure enough, what should have happened is all of them should have marked as red. Great. But we can do this in one line using a Laravel custom collection.
04:18
And that's, of course, exactly why you've clicked on this video. So just over in app, it doesn't really matter where you put this, depending on the size of your project. I'm going to create a collections folder.
04:28
And inside of here, I'm going to create a custom collection. So I'm going to call this NotificationCollection. And let's just start to build this out. So this is a NotificationCollection.
04:42
And this needs to extend. If we just pull the namespace in at the top there, this needs to extend the BaseLaravelCollection. So we're going to go ahead and extend either the EloquentCollection or the StandardCollection. But since we're working with database models, we're going to extend the DatabaseCollection
04:59
here. And that wouldn't have done anything at the moment, of course. But if we just take a look inside of the BaseModel for Laravel, let's just search for collection and just go down until we find something that looks like it could override which collection
05:13
we use. And you can see here, we come down to this method, NewCollection. Now, of course, by default, what this is doing is taking the array of models which have been taken out of the database, and it's putting them into a new collection.
05:25
And of course, this is public. What we can go ahead and do is just override this. And then we can specify the NotificationCollection, which, of course, extends the BaseCollection. So we know that this is going to work in exactly the same way.
05:40
So now what's going to happen is if we just get rid of this for now and just die dump on our notifications, previously, this was a StandardCollection. But when we refresh, we now get a NotificationCollection. And what this means is we can head over to our NotificationCollection and we can start
05:55
to implement methods on here that might be useful. So for example, we might have a MarkRed method in here. And let's just die dump on this for now. In fact, we can say this Get.
06:07
In fact, let's just leave it at this, and then we'll see what happens. If we come over to here now and say this Notifications MarkRed, what that's going to do is allow us to perform a batch of operations on here so we can get rid of this redundant code that we'd commented out.
06:21
Now, at the moment, that's not going to do much. It's just dying and dumping on the model. But now what we can do inside of here is say this Each. So much like we did outside of this, but now we're doing it internally so it's a little
06:32
bit clearer and more reusable. Taking each of the notifications inside of here, and let's just die dump on the first notification. And you'll see that this just represents a normal notification model.
06:44
So for each of these loops, what we can now do is say NotificationMarkRed. And that will just tidy this up for us. We can do this now in one line. Let's go ahead and get rid of the die dump on here, and we'll see what this does.
06:56
So if I just head over here and mark all of these as null, go ahead and save the changes here. Give that a refresh. Sure enough, we get exactly the same result.
07:06
This is probably one of my favorite things to use custom collections for. There are other uses for custom collections, and we're going to look at another use for that just now. Okay, so let's close all of this off so we can take a look at another use for this.
07:20
So let's cancel all of this off. We're still going to keep the user out in here. What I'm going to do is I'm just going to head over here, and I'm going to create a user setting model.
07:30
So this will allow us to store a key value pair of settings for a particular user. We don't need a factory for this because we're going to be manually creating these. So let's go ahead and create our A settings table. So let's come over to our migration.
07:44
Now, of course, this needs to belong to a user, and this is again my favorite way of creating settings for users rather than having each setting type defined as a column in the database. So let's say that this belongs to a particular user, of course, because it needs to reference
07:59
a user ID. And we're going to again make this unsigned, and we're going to make this an index. And of course, you can set up a foreign key constraint there if you want to. And let's go ahead and just create a string in here called key, and then create another
08:12
string in here called value, and we'll make that nullable. So essentially, what this allows us to do is have a long list of rows that represent keys and value pairs for user settings. For example, if you're watching this on the CodeCourse website, this will have something
08:26
inside of the key like player speed, and value will be the speed that you've chosen for the player, and that will save that in your settings. Okay. So let's come over and run phpArtisanMigrate to get that database table set up.
08:40
And again, let's come over to the user model, scroll down, and just create another relationship in here for these settings. And this is going to work slightly differently because we don't necessarily want to batch update settings.
08:50
That doesn't make sense. But we do want a convenient way to access the setting keys. So let's go ahead and create a setting just inside of there, pull the namespace in for that, and we should be able to access the user settings now.
09:01
So let's die dump on user settings, and let's head over to the browser and just give that a quick refresh. And of course, we've got an empty collection of no items. Okay.
09:12
So let's come over here and look at how we might traditionally access settings. The first way is to create a setting. We would say user settings, and we might say something like first or create. So we don't go ahead and recreate another row for a particular setting.
09:28
And we'd say key in here, and let's say player speed, and then we would have a value in here, maybe something like two. So if we go ahead and give that a refresh over in the browser, we should end up with if we go ahead and assign the fillable fields in here.
09:45
So let's head over to setting and just do that very quickly, so protected fillable, and let's set that to key and value, like so. Let's give that a refresh over in the browser, and sure enough, we end up with a record in here with player speed set to two.
10:04
So now what we can do is access whatever we've stored. So let's say user settings. How are we going to do this? It would be lovely if we could say something like user settings player speed.
10:16
That would be really nice to use in our code, but unfortunately, we can't do this because the collection that we're currently using doesn't have a player speed property, of course. So what we'd have to do in this case, every time we wanted to access the player speed, we'd have to say something like where key is player speed, and then go ahead and get
10:37
that value. So we could say something like first, and we'd probably have to access this as the actual relationship so we can query that inside of the database, and sure enough, we get the value inside of there, then we can extract the value out there.
10:50
Now the goal of this is to make this a lot shorter, so we do something like user settings player speed. So how are we going to do that? Well, the answer, of course, is using a custom collection.
11:03
So if we head over to the structure of this collection and just copy this over to a setting collection or a user setting collection, whatever you want to call it, let's just close this off, reopen it up, and just switch this over to setting collection. Get rid of mark red because, of course, that doesn't relate to this, and let's head over
11:20
to our setting model and create out that new collection like we did for our notification. So if we just come down, grab that method again, and pop that in there, and change this over to our setting collection. Go ahead and pull the namespace in for that.
11:36
And sure enough, we end up with, if we just head over to here and get rid of that key, the following. So we've got a setting collection. So the way that Laravel works is when we end up with a collection, we can actually access
11:51
via a proxy certain things. And to demonstrate this, let's just come over to the collection model, so illuminate support collection, and you can see that we have here a list of proxies. So we can use something like group by key by map max, for example.
12:07
So let's just, as a silly example, say we wanted to sum up the IDs of our settings. Well, of course, that's going to give us one. Of course, that's completely useless, but that is pretty much how it works. Now the way that this does work is if we head down to the get magic method, which is the
12:24
magic method in PHP, which allows us to access a key that doesn't actually publicly exist on a model, you'll see here if we don't have a particular key that we're trying to access inside that list of proxies, then we throw that exception that we saw earlier. So when we try and do something like the following, player speed doesn't exist within that proxy
12:45
list. So we throw a new exception, like so. So what our job now is to do is override this get magic method. There are other ways of doing this, but I find this way a little bit better.
12:56
If we head over to our setting collection, we can just pop that in there, make sure that we pull the namespace in for our exception and also the higher order collection proxy as well, and we give that a refresh. We just get exactly the same result.
13:08
Of course, we've not done anything inside of here that's useful just at the moment. Now essentially what we want to do in here before we check if this exists as a proxy, we want to check if any of the keys that we have in the database for that user, e.g. player speed, player quality, whatever you have in there, actually exists.
13:29
So let's just duplicate this row and add in a quality option and just set that to HD and see how we can pluck out a list of these keys. That's pretty straightforward. Let's just die dump here and say this pluck key.
13:43
So from the list of their models, we're going to grab that and we're going to cast that to an array. So what we'll end up with now is the following. So we've got player quality and player speed.
13:52
So what we can do is use a similar check like this, but use this to check if we have the key that we're trying to access inside any of these keys for that user setting. So let's create an if statement in here and just die dump and say OK if this evaluates to true.
14:09
And we're going to say in array. So we're looking if the key that we're trying to access exists within that plucked set of keys that we have stored in the database. And of course, you'll expect to see this say OK because we do have player speed in
14:23
there. If we choose something else, you'll notice that we get the same error, property ABC does not exist on this collection instance. So now what we can do is inside of here, we can go ahead and return a where clause or
14:37
a result of a where clause. So we can say this where key equals the key that we're trying to access. We can go ahead and use first and then we can go ahead and grab the value just out of here.
14:49
And we can grab the value inside of the database column. So let's go ahead and do that and you'll see that we get two returned. The only issue with this is of course it's going to cast it to a string. You're not always going to get the value that you want stored in the database because of
15:03
course this is just a string value. It's not a numeric value but you can go ahead and cast them where you need them. So there are two examples, two of which I use all the time for custom Laravel collections and how useful they are.
1 episode 15 mins

Overview

Custom Laravel collections add another level of fluency to your code. Let's take a look at a couple of examples to get you started.

Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!

Episode discussion

No comments, yet. Be the first!