در حال بارگذاری ...

Using Field filterable0:01

OK, so we're all on the same page. When I say filter, I'm talking about the options that appear in this drop-down on the right of any index inside Nova. By default, you'll just see perPage, so you can adjust how many items are shown on every page. But obviously, that can be altered and added to, and we've done that in previous episodes. Now, just to show you a basic example, imagine we want a filter on the JoinedAt column of our customers index. Let's go into the IDE and add that quickly. So, here on our DateTime JoinedAt field, I'm going to chain on the filterable method, which we've covered before. And by adding that method, which is available on many of the fields Nova provides, the filter drop-down will now have a JoinedAt from and to range input. Let's say I'm interested in customers who joined this month.

the filter drop-down will now have a JoinedAt from and to range input. Let's say I'm interested in customers who joined this month. Well, I can simply select that date range inside this filter, and now only customers who joined in the month of June 2023 will be shown in my index. Most of the time, that's all you'll need when it comes to custom filtering. But there are cases where you'll want something a bit more advanced and a bit more custom. For example, a customer can have reviews. Now, if I try to chain filterable on here, you'll see nothing comes up in my auto-completion, because filterable doesn't exist. And sure enough, if I try to refresh the index, I'm going to get an error.

Generating Custom Select Filter1:26

because filterable doesn't exist. And sure enough, if I try to refresh the index, I'm going to get an error. You cannot, by default, filter on a MorphMany relationship. So, we need to build our own filter for this. Nova makes it incredibly easy to build out custom filters. Let's create one using an artisan command. I'll type php artisan nova:filter. Then we have to name the filter. I'll call mine HasReviewsFilter and hit Enter to generate the file. The default filter that will be created is a select filter,

I'll call mine HasReviewsFilter and hit Enter to generate the file. The default filter that will be created is a select filter, which just so happens to be the filter type that we're actually interested in for our particular use case. I'm going to scroll down to the bottom where we have this options method. Now, options is a key value array. The key is what should appear inside the dropdown, and the value is what will actually be provided to the backend in order for you to apply the filter. I'm going to use Copilot to expand this, but I'm actually going to alter the values here. I'm going to say greater than or equal to for HasReviews, and I'm going to say less than for NoReviews.

I'm going to say greater than or equal to for HasReviews, and I'm going to say less than for NoReviews. And you'll see why in just a moment. In order to apply this filter to our Customer resource, we need to jump into the customer resource and scroll down until you find the filters method. Then you just need to pass an instance of your filter to this array here, and once you've done that, you should see the filter appear inside the dropdown here. I'm going to clear the join that field so that we have a little bit more to work with, and if I dropdown HasReviews filter, you can see we have three options, null being nothing, we don't apply the filter at all,

Applying Relationship Filter Logic3:03

and if I dropdown HasReviews filter, you can see we have three options, null being nothing, we don't apply the filter at all, HasReviews being the first option, and NoReviews being the second. Now, currently, clicking these will do nothing. It will reload the index, but we haven't actually filtered any data, and that's because we haven't told the filter how to apply our particular options. Back in HasReviews filter, I'm going to come down to the apply method, and I'm going to chain onto query the whereHas method, which allows us to check for the existence of relationships. In our case, we want to check for the existence of the reviews relationship,

which allows us to check for the existence of relationships. In our case, we want to check for the existence of the reviews relationship, and this is where my options greater than or equals or less than comes into play. Because if you look at where has, you'll see the default is an operator of greater than or equals to a count of one. So, in our case, we can just override the operator parameter and pass the value. In other words, if we've selected that we only want to show customers that have reviews, well, then we're only searching for customers where they have greater than or equal to one review, and if we say we want customers with no reviews, well, the opposite will happen. Now we're only searching for customers where they have less than one review.

and if we say we want customers with no reviews, well, the opposite will happen. Now we're only searching for customers where they have less than one review. So, with this very basic filter in place, we should now start seeing this applied. You can see I now only have five items inside my customer index. If I select no reviews, we have 65 items, and if I select all reviews again, I would expect 70 items. Sure enough, we do have 70 items. So, yeah, pretty straightforward to implement a custom filter like this and begin using it inside your index. Let's tackle another use case that's perhaps a bit more complicated.

Building Date-Based Loan Filter4:51

and begin using it inside your index. Let's tackle another use case that's perhaps a bit more complicated. Obviously, customers can loan books. What if we want a filter on the customers index that allows us to select customers that loaned a book within a certain time frame? Let's implement that using a date filter. From the terminal, again, we'll type php artisan nova filter, and we'll say LoanTimeFrame from filter, and we want to use the date type, so I'll use the --date flag in the artisan command. The logic here is fairly simple.

and we want to use the date type, so I'll use the --date flag in the artisan command. The logic here is fairly simple. We, again, have an apply method, and how this will work is we'll receive a value which will be the date that we want to apply to. Now, obviously, we want to build a date range, but we'll tackle that in a moment. For now, we're just going to do from, in other words, the start date of a loan. In our case, we want to extend this query to say whereHas. We're looking at the allLoans relationship, and we'll pass a closure which will receive the subquery that we want to make alterations to.

We're looking at the allLoans relationship, and we'll pass a closure which will receive the subquery that we want to make alterations to. Now, the field that will actually tell us when a book was loaned from is the created_at column under the book_customer pivot table, so we need to target that in our code. We can say something like query->where('book_customer.created_at', '>=', $value) that we've passed up here using Carbon, and this should actually suffice for the query we're creating. Let's apply this filter to our NovaCustomer resource, so new LoanTimeFrameFromFilter,

Let's apply this filter to our Nova customer resource, so new loanTimeFrameFromFilter, and hopefully we should now see this inside the customer index. loanTimeFrameFromFilter. Okay, let's go ahead and choose something like February the 1st, 2023, and hopefully, yeah, we now only have 20 results, which means the filter has been applied correctly. We obviously want the other end of this, the loanTimeFrameToFilter, so we'll copy and paste this filter and make the needed adjustments. I'll duplicate the filter and I'll rename from to to,

so we'll copy and paste this filter and make the needed adjustments. I'll duplicate the filter and I'll rename from to to, and we should just be able to alter this >= to be

Refactoring Into Dynamic Filter7:34

was pretty much identical apart from the difference in an operator, so when that's the case, you can actually create dynamic filters that allow you to reduce code duplication. Let's refactor our loanTimeFrame from filter to make it dynamic. I'm going to implement the constructor, and I'll pass in a private string, which is an operator. Down in the apply method, we should now just be able to replace the operator we've passed here with the operator we've passed into the constructor. Now, obviously, we'll want a more descriptive label above the filter, and you can override the name function in order to create whatever label you want for your filters.

Now, obviously, we'll want a more descriptive label above the filter, and you can override the name function in order to create whatever label you want for your filters. So in this case, I'm going to return a match statement, which is given the operator, and using that operator, we can say, well, if it's less than or equal to it's loansBefore, if it's greater than or equal to, the label can be loansAfter, and by default, we'll say it's going to be loansOn. We also have to override the key method when using dynamic filters. The key method tells Nova how to track a filter across requests, so it's important that they're unique for each page. Because we're going to have this same filter twice, we need a unique key,

so it's important that they're unique for each page. Because we're going to have this same filter twice, we need a unique key, and obviously, seeing as the name is unique, we can separate it by that. So we'll say loanFilter, and then I'll use the name method in order to make the key unique across the page. We can now rename this filter to get rid of the from, and just call it a loanTimeFrameFilter, and obviously, when we use that inside the customerFilter method, we're going to have to pass a >= sign here, and then I'll duplicate it and pass a <= sign as the second filter instance.

we're going to have to pass a greater than or equal sign here, and then I'll duplicate it and pass a less than or equal sign as the second filter instance. In the browser, the result should very much be the same. We have loans after and loans before. Let's go ahead and select February 2023 again, so we have 20 results, which is to be expected, and then if I select February 2023 for loans before, I should see just 10 results now, and sure enough, I do. So dynamic filters allow you to reduce code duplication, but also make your code very flexible across different resources in your application,

Filters Recap and Options9:44

So dynamic filters allow you to reduce code duplication, but also make your code very flexible across different resources in your application, and well, that's filters. All you're essentially doing is altering the index query that Nova will execute on your resource. Most of the time, the filterable method will do just fine, but if not, no sweat. Create your own custom filter, a date filter, a Boolean filter, a select filter, and remember you can make those filters dynamic by passing in parameters for ultimate flexibility.

and remember you can make those filters dynamic by passing in parameters for ultimate flexibility.

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