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

Designing Pivot Table0:00

[MUSIC PLAYING] Now we have a way for the users to browse the books. Next, the main feature of our app is the ability for users to be able to request for books, see what they've requested, look at the books they're currently reading, and also look at the books they've read before, which means multiple users can request multiple books. That's a many to many relationship, so we need a pivot table, let's create that. Let me open terminal, right?

so we need a pivot table, let's create that. Let me open terminal, right? We need the primary key ID, because we're going to make this a book user's risk source as well, and filament, so let that be. Now let's create the foreign ID for book class, same goes for users, and then we need a status column to see if the user has requested it, or is it borrowed, is it currently reading? So that is, yes, exactly this.

or is it borrowed, is it currently reading? So that is, yes, exactly this. So we have three status requested, borrowed, and returned. I'll leave this comment here for reference, and then we have a tiny integer, which is the rating. So users who have read the book can give it a rating from 0 to 5, which is tiny, unsigned, tiny integer, rating, exactly that. And then we do have a text review that users can leave, which is also nullable.

And then we do have a text review that users can leave, which is also nullable. And then we have a timestamp requested at, and we have a borrowed at timestamp as well, and returned at times. Another thing we would need is, once the user has requested a book and is currently reading it, that is, it is in the borrowed status, and the user wants to return it. So he or she requests for pickup,

and the user wants to return it. So he or she requests for pickup, because the user cannot directly change the status to return, and the admin cannot directly change it. It has to come from the user. So we have another timestamp here, which is return requested at, and nullable. Probably we can add timestamps. That's optional. And yes, this is not book users, it's book user.

Creating Pivot Model2:23

That's optional. And yes, this is not book users, it's book user. Okay. Next, we also need a pivot model, because we need some relations, and it'll be easier if we actually have a pivot model. Let me close this, and open the terminal again. Create a pivot model, book user. And this has to extend pivot. Let's mention the table, mostly not needed because we followed the convention,

Let's mention the table, mostly not needed because we followed the convention, but let's do this. There's another thing we need to do here. We need to set an incrementing variable. Public incrementing is true, because though we are using a pivot table, we have the primary incrementing ID. So we have to mention that it exists, and it has to be incrementing.

So we have to mention that it exists, and it has to be incrementing. This has been auto-completed for us, so I think it's perfect. We need some more here, and now we need the relations, which has also perfectly been auto-completed for us. Let me close this, and migrate. DHV artisan, great. All right.

Seeding and Relations3:32

DHV artisan, great. All right. Now we need some data to play with. So I've already created a user cedar, with just about six users, and also a book user cedar, where I take each user, randomly pick a few books, and then set a status, add some timestamps of when it was requested,

and then set a status, add some timestamps of when it was requested, when it, whether it was returned, and also add a random rating. Let me see this now. DHV artisan, DB seed, plus user cedar. Oh, I also need to do the book user cedar. Okay, looks like I didn't define this relation. So let's go to the user model,

Okay, looks like I didn't define this relation. So let's go to the user model, define the many to many relation, and let's do the same in the book model as well. Now we should be able to seed, PHP artisan, DB seed, book user cedar. It's done. It's just to verify fresh. Yeah, we do have a lot of activity going on here. We have some users as well.

Building Filament Resource4:43

Yeah, we do have a lot of activity going on here. We have some users as well. Perfect. Now it's time we create the book user resource. PHP artisan make filament resource. The model is book user. And there is no title attribute. I'll leave it blank. I need it in the app panel right now, and no, should the configuration be generated?

I need it in the app panel right now, and no, should the configuration be generated? I guess, yes, let's see what it gives us. Let's just look at the browser and see what it's given us. We have book users here. Of course, the label is not appropriate. We'll change that in a much later episode. For now, it says book users. And of course, we have all the activity going on

For now, it says book users. And of course, we have all the activity going on of other users as well. We don't need that. We only need the books that we have requested or borrowed. So let's modify the Eloquent query. So right here in the book user resource, let's add the public static function. Get Eloquent query. Yes, return parent.

Get Eloquent query. Yes, return parent. Get Eloquent query. Where user ID is only the authorized ID, which means the signed-in user. I need to declare the return type. Now let's look at this refresh. Yes, we have only the requested books of John. Now we need to change the columns here. We don't need the user.

Now we need to change the columns here. We don't need the user. We need the book title, all of this. Actually, I think we can copy the table structure from here because we need to see the same things, right? The cover, title and author. So let's take the columns from here and the content grid. Copy this and replace these columns, many of them with what we copied. Say, okay, I will just remove all these for the moment.

many of them with what we copied. Say, okay, I will just remove all these for the moment. We might add them back. Okay, let's see, refresh. Okay, looks like since this is a relation, we can't directly fetch image, title and author like so. We need to say book.image, book.title and book.authorism. This should give us refresh, yes. So right now, all these four books,

Filtering with Tabs7:04

This should give us refresh, yes. So right now, all these four books, I have no clue which one I'm currently reading, which one I have requested. This is my activity. So let's filter this table using tabs. If you go to the filament documentation, resources, listing records, it shows you how you can use tabs to filter the records. So let me just copy this and paste this

to filter the records. So let me just copy this and paste this in the list book user, I guess. So let me open listbookusers.php exactly. We don't need this header action. That's not how we create it. Let me paste this get tabs here, import tab and we also need three tabs. That is the first one is requested status. The next is borrowed

That is the first one is requested status. The next is borrowed and the last one is returned. We have to modify the query for each one of them. Like so, modify query using builder, import again and here where the status is requested, right? Let's see what this gives us, refresh. And yes, we do have the requested, borrowed and returned. Looks like the CDO gave us only four requested books. So I'm gonna just quickly go to the table

Looks like the CDO gave us only four requested books. So I'm gonna just quickly go to the table and make some changes. All right, so here I've just made some changes. Let me refresh. Yes, we do have two requested books, should be one borrowed and one returned. It would be great to add some icons for these tabs, right? Add an icon here using the icon method and this is the requested books.

Add an icon here using the icon method and this is the requested books. Yes, so hero icon o'clock would be good which says it's pending. And here let's add an icon which is book open, perfect. And return books, let this be, yeah, check, circle. Okay, let's look at this. This is great. Let's also add a badge here to show the count of each of the books.

Let's also add a badge here to show the count of each of the books. Right here, let's use the badge method and it's auto-completing something like this. Function, auth, user. Yes, auth user, book users, no, we called the relation as books where status requested count. That sounds right. All right, I've added the badges and the other two tabs as well.

Empty States and UI Tweaks9:50

All right, I've added the badges and the other two tabs as well. Let's see, refresh. Yes, we have the count, perfectly done. Okay, the filters are great, but how about empty state? That is when we don't have any of these books. So let me quickly remove all the books of this particular user. So once we remove all the books, this is what we have. It suddenly says no book users.

So once we remove all the books, this is what we have. It suddenly says no book users. This is not the heading we would like for any of the tabs. So let's make it custom. Go to the code, go to book user stable. So this is where we can add an empty state heading or empty state actions, empty state icon, empty state description and so on. So let me first add empty state heading, but we cannot hard code this.

So let me first add empty state heading, but we cannot hard code this. We have three different tabs. We need three different headings. For that, what we can do is we can pass a method and inject the live wire utility so that we can get the active tab. So we can say active tab equals live wire active tab. Or null. And then we can return match active tab.

Or null. And then we can return match active tab. So yes, if there are no borrowed books, we say you have not borrowed any books yet. You have not requested any books yet. And you have not read any books is what I can say. And default is no books found. Of course, we can simply remove this variable. It's not required. Let me add this directly like so.

It's not required. Let me add this directly like so. Let's see if this works. Refresh borrowed not read. It's also great if we could add an icon, right? Instead of just a cross for that, let's add empty state icon. And this could be common. We can simply use a book open icon like so. And we can have a custom action

We can simply use a book open icon like so. And we can have a custom action where the user can request any book. But that is something we'll do in a future episode. Now the filtering is done. Next, let's look at the search. Here in the book user's resource, as well as the book's resource, you can search by title like shadows or by the author, say Caleb like so.

you can search by title like shadows or by the author, say Caleb like so. And that's because filament automatically added searchable method for both our columns. Right here, the text column book title is searchable and text column author is also searchable, same in the books table. But the placeholder of the search input simply says search, which is quite ambiguous. So let's change this placeholder in both the tables.

which is quite ambiguous. So let's change this placeholder in both the tables. Right here to search placeholder method. And we say search by title or author. And let me add this into book user's table as well. In the end, okay, let's check refresh. Yes, we're able to see the placeholder, but definitely the search input is quite small. We'll fix that later. We're able to see this in both these resources.

We'll fix that later. We're able to see this in both these resources. So I feel this global search in the navigation bar is quite redundant. It doesn't really serve the purpose. So let's remove this. This is done in the panel configuration. So let's go to the base panel provider because we might remove it in both the panels. And right here, use the method global search

because we might remove it in both the panels. And right here, use the method global search and set it to false. Here, refresh, that looks much neater. And the last thing is the pagination. Now, we might see very few books. The user might see only a couple of books and requested, maybe one or two in borrowed, but this looks quite odd. It looks unnecessary here.

but this looks quite odd. It looks unnecessary here. To remove this completely, what we can do is we can set this array to just a single number. So let's go to the book user's table. Here, let's use the method paginated and pass an array of a single digit, like so, like just one number instead of multiple. Now refresh and it's gone.

like just one number instead of multiple. Now refresh and it's gone. Let's change this in the book's table as well. Use the paginated method and instead of 10, we can add 12 because at Excel breakpoint, we're showing three. So 10 might look quite odd, we'll have one left over. So now let's go to the book's table and we can see 12. It's just, we don't have to see the number here, and we see the next and previous buttons only.

It's just, we don't have to see the number here, and we see the next and previous buttons only. This is much cleaner. We'll do more in the next episode.

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