تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Fixing Failing Tests0:00

Just before we dive into our next section, I have a couple of failing tests on the show test for a PostController. So if I run this, our first failing test is it passes a post to the Vue. I think essentially we just need to tag on the with like permission to the post resource in the test itself. Yep. And the second failing test is it passes comments to the Vue. Same thing, but this time with a collection. So we need to extract this. Let's say expectedResource equals CommentResource collection. And then we'll need to say expectedResourceCollection. We'll need to transform that collection, so each item. And we'll be passed an instance of the CommentResource.

We'll need to transform that collection, so each item. And we'll be passed an instance of the Comment resource. And we'll want to say with like permission on each of those resource items. And then we can pass that expected resource back into assertHasPaginatedResource. Let's run that again. And you can see that it passes. So now all of the tests inside our project are passing, and we're good to carry on. Now, really, there's no end of features and ideas that you can tack on to a project like FrameRate. You could go on forever. It's just not possible when it comes to a video series.

Introducing Post Search1:16

You could go on forever. It's just not possible when it comes to a video series. So there's one last topic I want to touch on before we bring this to a close. And that is being able to search using free text for posts inside frame rate. I think that's a very important feature for any forum to include. And there are varying levels of complexity you can go to to make it possible inside your applications. So we'll start with a nice basic SQL implementation, and we'll work from there. Let's get started. I know that throughout the series we've been using a loose form of TDD. But for this particular feature, I'm going to move away from TDD.

Implementing SQL Filter1:48

I know that throughout the series we've been using a loose form of TDD. But for this particular feature, I'm going to move away from TDD because I'm just going to be playing about with ideas, and I don't want the tests to constrain me in any way until I've settled on the final solution. So in index, I'm going to accept the request in the method signature. We're inside our PostController here. And, well, we already filtered down by topic, but I want to add a secondary filter. I only want it to be the case when we pass a filter in. So we'll check using when for a query parameter. And I think the standard for this is the word query.

So we'll check using when for a query parameter. And I think the standard for this is the word query. So if we jump into our front end, it would be something like this, right? query equals Spielberg inside the URL itself. So we'll first check, do we have a query called query? The second parameter is a closure, which accepts an instance of an Eloquent builder. We'll call it query. And then I need to perform some basic search function in SQL. I'll write the code first, and then we'll discuss what it does. So we'll have query.

I'll write the code first, and then we'll discuss what it does. So we'll have query. I'm going to use where. And I'm interested, first of all, in filtering on the title. So where the title is like, percent, and then the request query that's been passed from the front end, and then another percent sign. In case you're unfamiliar, the like term in SQL is going to allow us to perform partial checks inside a column in our database. So in this case, we're saying, look,

is going to allow us to perform partial checks inside a column in our database. So in this case, we're saying, look, I'm interested in any Post that has a title where there is any character, that's what this wildcard is, the percent sign, followed by whatever our query happens to be, followed by another percent character. And those are our wildcards. So anywhere inside the title can be the query text that we're interested in. Let's see if it works. On the front end, I'll manually update the query string here.

Let's see if it works. On the front end, I'll manually update the query string here. And how about we have singing? So that's singing in the rain. And you'll see that it does actually work. It's returned any of these posts that have the word singing in the title. And in this case, there's only one page of posts. However, it's also important that we provide the ability to search for text that might be in the body of a particular post. So, for example, we have Gene Kelly here.

to search for text that might be in the body of a particular post. So, for example, we have Gene Kelly here. Well, if I go back and update my query to Kelly, that's not going to work at all. Zero results are returned because no post title has the word Kelly in it. Now, we could do this, as you imagine, with an orWhere query. So I can drop a new line in here. We can say orWhere, and I can update this to body. And now I would expect if I come back and refresh, all of those singing in the rain posts reappear.

And now I would expect if I come back and refresh, all of those singing in the rain posts reappear because they have Gene Kelly inside the body. But we can actually shorten this syntax because recently Laravel received a new helper called whereAny. And we can specify an array of columns to search against. So either where the title is, like, or where the body is, like. And that allows us to remove this duplicate code. We can simplify that to a one-liner. And we're left with this nice, clean solution.

Building Search Form UI4:53

We can simplify that to a one-liner. And we're left with this nice, clean solution for like searches across the title and body of our Post. There we go. That's the back end taken care of. Let's go ahead and update the front end so that we have a nice search form rather than having to update the URL manually. We'll jump into posts/index.blade.php. And perhaps just under our topic menu, why don't we add a form? Let's dive into the form here, and we'll add a div.

And perhaps just under our topic menu, why don't we add a form? Let's dive into the form here, and we'll add a div. And that div is going to contain, well, first of all, our input label. Let's call this search. And it's going to be for the query input. Then we'll have our actual input, which is a text input. That's going to have an ID of query. We'll add a little bit of spacing to the top, maybe MT1. Let's also make sure it takes up the full width. Let's see what that looks like.

Let's also make sure it takes up the full width. Let's see what that looks like. Okay, not looking bad at all. We'll add a little bit of spacing above the form, maybe mt-4. Yep, that's nice. And, of course, we'll want an actual search button. I think I kind of want that in line to the right of the search field itself. So let's wrap this in a div. And then let's go ahead and add a little spacing between elements. So class equals space-x-2, and we'll make this flex.

And then let's go ahead and add a little spacing between elements. So class equals space-x-2, and we'll make this flex. Okay, now we can add maybe a secondary button. I don't want it to be too bold on the page. So secondary button called search, and we'll give this a type of submit. There we go. And I just want to fix the height differential here. I think that's because we've got mt-1 on the text input. So let's put mt-1 on the div instead. And nice.

So let's put MT1 on the div instead. And nice. Now the search button is the same height as the text input. Of course, we need to actually wire this up so that it works as a form. So we'll listen on the form for submitting. I'll prevent the default action. And then we'll have a little action called search. And while we're here, we'll add the v-model to our text input. So v-model equals, we'll create something called a searchForm, and we'll have a property called query on that form.

So VModel equals, we'll create something called a SearchForm, and we'll have a property called query on that form. Okay, let's come down to our script, and we can add this at the bottom. So const searchForm equals useForm. We'll make sure that's imported from Inertia. Yes, it is. And then we can add that property query, which by default can be set to an empty string. Then underneath we'll have our function, which is search. So search is going to submit the searchForm.

Then underneath we'll have our function, which is search. So search is going to submit the search form. In other words, we can say search form.get, because we want to make a get request. And we'll want to go to the post.index root. There we go. Let's see if it works. We'll jump into the front end. Let's search for singing, as in singing in the rain. And, yeah, you can see that did work.

Let's search for singing, as in singing in the rain. And, yeah, you can see that did work. What if we search for Kelly instead? Yep, it's still only showing singing in the rain, and you can see the query did update at the top. Now, one thing I'm noticing is that as we perform a search, let's try singing again, it disappears. So we don't see a consistency when you actually submit this form. Let's see if we can fix that. Back in the IDE,

Persisting Query Input8:03

Let's see if we can fix that. Back in the IDE, we could just set this to actually detect what's inside the URL. There is an API in JavaScript for that, but I think I'm going to do it from the back end. So inside our PostController, when we pass things down as props, I'm also going to pass a query down, and that will be set to whatever you've passed in the query parameters. And then on the front end in post.index,

and that will be set to whatever you've passed in the query parameters. And then on the front end in post.index, I can add that as a prop. So that will be called query. We'll assign these to a props constant. And then for the search form, I'll set that to be equal to props.query, like so. So now, hopefully, if I refresh the page, yeah, see how that now replaces itself with singing? If I change this to Kelly and submit,

yeah, see how that now replaces itself with singing? If I change this to Kelly and submit, Kelly stays inside the search box. And it doesn't matter how many times I refresh, that is always going to be the case. So we have ourselves a nice, simplistic solution for being able to search by title or by post body. And you know what? For some projects, this is all you actually need. You don't need to go any further than this.

Noting Edge Cases9:07

For some projects, this is all you actually need. You don't need to go any further than this. There are, however, a few edge case bugs with what we've just created. So let's touch on those and fix them in the next episode.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟