This episode is for members only

Sign up to access "Easy Query Filters with Laravel Pipelines" right now.

Get started
Already a member? Sign in to continue
Playing
03. Creating our first filter

Transcript

00:00
Now that we know how pipelines work, it's time to create some data
00:04
and actually create a useful pipeline for our query filters. So we'll just include one filter here and then we'll talk about some of the nuances around what we can do with pipelines. So the first thing to do is obviously create out a model
00:17
for the discussions that we're going to be creating. So let's go ahead and create out a model here for discussions and we'll create a migration and you could create a factory. We're just going to manually add the data here.
00:30
Okay, so let's go over to that migration, create discussions table. I've already migrated the migrations that come by default with Laravel with the users in here. What we're going to be doing with this discussion
00:40
is just keeping it really, really simple, not even assigning this to a user ID. Of course, you would normally do that. We're just going to be adding a title in here
00:48
and we're going to be going ahead and adding a timestamp specifically whether this is solved. And we saw this from the introduction. That's going to be nullable because it might not be a solved discussion
00:58
and that's pretty much all the data that we need to make this work. Okay, so let's go ahead and run phpArtisanMigrate, get that in there and we can actually start to pluck some of this data out. So let's go ahead and say discussions
01:10
and let's just use to start with discussion get and let's pass this down to this view which I've already created. It's just an empty template at the moment. So pass them discussions down
01:21
and at the moment we've just got forum index. Let's iterate over these discussions so we have something to output. So if we head over to that index file, let's go and create this out really quickly.
01:32
So we're going to want to go ahead and do a for each on them discussions as discussion and in here we'll just create a div wrapper and let's output the discussion ID just so we can see that a little bit better. We'll go ahead and grab the discussion title
01:51
and finally let's finish up with an if statement just to check if this discussion has been solved. If it has, we'll output solved in brackets just here. So at the moment we're not going to see anything because we don't have any data
02:04
but let's head over to the database and just manually create out two discussions. So let's just say discussion one. We'll not make that solved and we'll go ahead and create another one and just call this discussion two.
02:19
Not very inventive and we will make this solved. So our first filter is going to be returning any discussion that hasn't been solved e.g. solved at is null. So at the moment if we head back over we should just find two discussions.
02:35
We don't so let's just take a look in here. Name that properly and there we go. Okay so there's a couple of ways that we can start this out in terms of our pipeline. We can go ahead and start off our maybe default ordering.
02:50
So we could say discussion latest. Now it's really important to note that what we're not doing is saying discussion latest get which returns to us a collection and then passing that through a pipeline because then what we'd be passing through a pipeline is a collection
03:06
and we wouldn't be able to add builder methods onto this with Eloquent. So we're just going to leave this as latest which actually gives us back a builder instance which we can pass through as the thing we want to go through our pipeline. Just to give you an example of that let's go ahead and die dump on discussions
03:24
and you can see we get a builder in here. So we can pass this discussions builder through a pipeline and each of the pipes based on the query string is going to go ahead and modify that builder. So let's go and just assign discussions to something slightly different
03:41
and that's going to be the pipeline out of our container. So we're going to go ahead and send that query builder through this pipeline and we're going to pass this through some filters. Now we're not going to do this as closures we're going to go ahead and just create our
03:58
straight up under the HTTP directory some query filters. So of course you can put these wherever you want and the first one is going to be an unsolved query filter and of course depending on how many of these you create
04:13
you can go ahead and categorize these a little bit better. So let's give this a namespace it's now under HTTP and query filters and we're just going to do exactly what we did in the last episode. Give this a class name and if you remember we're going to give this a handle method
04:30
which gives us the thing that we're passing in and then the next callable pipe. Now the thing that we're passing in is a query builder so we can just go ahead and type in this as builder from illuminate database and eloquent and we can do whatever we want with this in here.
04:48
Of course making sure that we always return the next piece of in this case not middleware but the next pipe using the next method. So now we can go ahead and take unsolved query filter and we can pass this in here. Now let's just die dump on discussions at this point.
05:07
What do you think will be output when we die dump on discussions? Well in this case it's still going to be a pipeline we've not returned anything just yet. So let's say then return and now what are we going to get? Well let's head over and if we actually pull the namespace in for this properly we get a builder.
05:26
So we have passed this builder through this pipe and then we've returned it. Now the beauty of this and the beauty of this method of creating query string filters is because we're getting a builder back from this we can now go ahead and say get like we normally would on something like this or which we're going to look at later
05:45
we could just straight up paginate this. So let's stick with get for now just so we've got that data in there and let's come over and have a look at what we've got. Now we're dying and dumping on this at the moment let's get rid of that
05:55
give that a refresh and there we go we get exactly the same data nothing's being modified at the moment in this unsolved query filter we're just going ahead and returning the next pipe or the last pipe and passing through that builder.
06:07
So what do we do in here? Well I'm going to show you one method of doing this and then we're going to slightly refactor this later so each of our filters is a bit more testable. We're actually going to write a test to cover one of these filters as well
06:21
just so you'll see exactly what I mean. So what I'm going to do is take a sort of defensive approach to this and I'm going to say well if we don't have any filters then we're going to return this next builder.
06:33
So how do we check these? Well in a more untestable way we could just use the request helper within Laravel which will give us access to the request and then what we can do is use has to check if we have the unsolved filter in here.
06:47
So if we don't have the unsolved filter we don't want to modify the query in any way we just want to return the next builder. Now otherwise what we want to do is return the next builder but we want to chain onto this the query that we would normally use
07:04
which in our case is going to be where null and solved at. So we're just building this query up as we need. Now there's another way to do this if you don't want to use a kind of defensive programming approach what you could do is you could say well if the request does have this filter
07:20
you want to return this like so otherwise outside of this you always want to go ahead and return the next builder so it's nice and clean. So it's really up to you which approach you use. I much prefer doing this in a more defensive way and returning the kind of default
07:36
if this hasn't been filled. So we're going to say if we don't have any unsolved filter just return the next builder. Hopefully that makes sense. So let's go over and just give this a refresh.
07:44
Sure enough nothing has changed until we go ahead and pull in that unsolved filter. Now the main downside to doing this is you would have to implement a lot of logic inside of each of these individual filters if you wanted to check for specific values. So at the moment if we look at what we've done in our code
08:04
we're only checking that unsolved exists as a query string. We're not checking the value itself. So we could pass one in here we could pass true we could pass x it really doesn't matter what we put in here as long as unsolved exists.
08:17
When we go ahead and pass that in sure enough we only get the discussion which has not been solved. So there we go very very quickly and very very cleanly inside of here we have implemented a query filter and of course it's now super easy to add more of these which we're going to be doing in the next episode.
6 episodes 35 mins

Overview

Applying result filtering with query strings can mess up your controllers quickly. Let's reach for a solution using Pipelines, an undocumented but seriously powerful feature of Laravel.

Every filter (e.g. only show activate users) will have its own class, neatly tucked away. We'll also cover testing, and see how this method makes isolated testing much easier.

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

Episode discussion

No comments, yet. Be the first!