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

Planning First Feature0:00

Okay, let's start implementing the actual functionality of the app. Now in terms of where to start, I personally like keeping it simple and picking a small feature to begin with. So in this case, I want to start with listing the Ideas and making that dynamic. So this will force us to create the models and migrations we need to implement this feature. So in the process, we're also going to be breaking out into components. So specifically for this episode, we'll make a component for the Idea card here. And initially, I just used Blade components, but later on, I switched it to Livewire components. So we'll install Livewire. And let's also install the Laravel Debugbar to monitor our performance when working with.

Installing Livewire and Debugbar0:33

So we'll install Livewire. And let's also install the Laravel Debugbar to monitor our performance when working with database queries. So let's quickly do that. Start with Livewire here, let's composer require it. And let's include the assets. So Livewire scripts or styles and scripts. So this will go in our layout, so app.blade.php. So let's put the styles up here. So we'll put it right here.

So let's put the styles up here. So we'll put it right here. And for the scripts, let's put it right here. Scripts, okay. Let's also install debugbar. So let's grab the composer require. Okay, so now there should be debugbar here. And there it is. So we need a new Idea model here. So let's begin with that php artisan make:model Idea.

Creating Idea Model Relationships1:28

So we need a new Idea model here. So let's begin with that php artisan make:model Idea -a. And it's a dash -a for everything else. So a controller, a migration, and a factory, I believe. Okay, and let's go ahead and open that up. And let's first set $guarded to an empty array. Now let's think about the relationship between Users and Ideas. So I usually just speak it out. So we have Users and Ideas. So a User has many Ideas.

So we have Users and Ideas. So a User has many Ideas. If you think about it, that makes sense because a User can create many Ideas. Or several Users can create several Ideas. So a User has many Ideas, makes sense. So let's do that first. Let's go to User, let's go down here, let's add a method here. Let's say ideas and it's return. This has many Idea class. Okay, and for the other way, so again, just speak it out.

This has many Idea class. Okay, and for the other way, so again, just speak it out. And if it doesn't make sense, it's not correct. Now, can an Idea have many Users? To me, that doesn't make sense because one Idea only belongs to one User. It can't belong to many Users. So the relationship is Idea belongs to User. So let's do that. So let's make a new method here. Say user and it's return.

Building Ideas Migration2:57

So let's make a new method here. Say user and it's return. This belongs to User. Okay, now let's set up our migration. So create ideas table. And let's see what we need here. So since an Idea belongs to a User, we need a user_id field here. So we can do table, we can do foreignId, and user_id is the column name. And if we used the constrained method, this will reference the users table. So that should do.

And if we used the constrained method, this will reference the users table. So that should do. What else do we need? We need a string. So table, not a string, a title, table string title. I also want a slug. So let's add that, string slug. And let's make this nullable. Okay, and a description. So table, let's make this text description.

Okay, and a description. So table, let's make this text description. And that's fine for now. So we do have other models and relationships. For example, we have this Status and we have the categories here. But like I said, I want to keep it simple and work with one thing at a time. So let's go ahead and php artisan migrate just to see if it works. But I also want some dummy seed data. So let's work on that as well.

Seeding Ideas with Factory4:24

But I also want some dummy seed data. So let's work on that as well. So we also created an IdeaFactory. So let's go to that. And let's add some fields here. So the user_id. And for now, we can just create a new User for each new Idea. We'll change this later on. So we can just do userFactory. Title, let's say this Faker, let's say four words.

So we can just do UserFactory. title, let's say this Faker, let's say fourWords. So this Faker words, fourWords, and we want it as text. And let's also use the uppercase ucwords PHP function. So we can uppercase the first letter in each word. Make sure to import User. And we'll add a description here. Say this Faker paragraph with five sentences. Okay, so now in our seeders file, so DatabaseSeeder, we don't need to create users because that's being done in our IdeaFactory.

Okay, so now in our seeders file, so DatabaseSeeder, we don't need to create users because that's being done in our IdeaFactory. So let's do IdeaFactory. Let's say 30 ideas for now and say create. Let's make sure to import Idea. Okay, and I'm going to migrate fresh with the --seed option. And I'm gonna use my alias here. So let's do which mfs so you can see the entire command. So let's run that. And now we should have some dummy data.

Listing Ideas from Database6:07

So let's run that. And now we should have some dummy data. So if I refresh this, there are 30 ideas here. Cool. And we also have 30 users. Okay, now let's work on our view here. So we have this view here. Let's replace this with the dynamic data from the database. So let's start with the routes file. And we no longer need this because we're going to use a controller now.

So let's start with the routes file. And we no longer need this because we're going to use a controller now. So let's get rid of this route get. So it's /. It's called IdeaController@index is fine. Say idea.index. So let's import IdeaController. And let's go to that. Oops, forgot to save my routes file. Okay, index.

Oops, forgot to save my routes file. Okay, index. Let's return view. And I have a view named index already, but I'm going to put it in an Idea folder. So idea.index. And we will pass through ideas. And for now, let's just do Idea::all(). Okay, let's import Idea. It's already imported. And let's move this index and also our show into a folder.

It's already imported. And let's move this index and also our show into a folder. So let's make a new folder here. Called idea. And let's move index and show into idea. Move. Okay. So does this render? It should still render if we did everything correctly. IdeaController 20.

It should still render if we did everything correctly. IdeaController 20. Forgot my semicolon here. Okay, so it still renders. But now let's go ahead and for each over all of those ideas. So in our index, so this entire idea container will be in its own component. So let me remove the other ones because I hard coded a few of them in here. So that's the first one. And I'm just going to delete the other ones for now. Okay, so there should only be one idea card now.

And I'm just going to delete the other ones for now. Okay, so there should only be one Idea card now. And there is. So let's go ahead and foreach over this for now. And then we'll move it to its own Livewire component. So let me end the foreach here. Let's go up here and it's indented. And let's add foreach here. Okay. And we can foreach over our ideas.

Okay. And we can foreach over our ideas. And say idea. And we can start replacing this information. So we're not doing votes yet. But for our title, we have that. So we can say idea->title. What else do we have here? We have the description here. So let's do that.

We have the description here. So let's do that. Actually, this is also going to be a link, which we haven't added yet. Actually, we'll do that after I add the other route here for showing a single Idea. So let's just put description in here. What else? We have the timestamp of when it was created. So right here, let's say. Idea created_at and there should be a Carbon instance so we can do diffForHumans.

Creating Idea Show Page9:38

Idea created at and there should be a carbon instance so we can do diffForHumans. I believe save that. OK. And now all of these ideas are being pulled from our database. So there should be 30 here. And it looks like there are. OK, now let's work on the single idea page. So back to our routes file. So instead of this, it's another get route. So let's say Route::get.

So instead of this, it's another GET route. So let's say Route::get. And it's going to be /ideas. Oops. And let's say Idea for route model binding. And it's IdeaController::show, say idea.show. And we don't need this anymore. Let's go to that controller.

And we don't need this anymore. Let's go to that controller. Let's go to that controller. So IdeaController. show. And the idea is being passed through, so we can just do return view idea.show and pass through this idea here. So say idea is idea. OK. And now we can fill in that link on the index page.

OK. And now we can fill in that link on the index page. So right here. So let's say route('idea.show'). And we're passing in the $idea. OK, see if this works. Refresh. IdeaController 54. Again, forgot my semicolon. And let's try clicking one.

Again, forgot my semicolon. And let's try clicking one. OK, so it does go to the page. We just have to make it dynamic. So we have the same information, but now we have the user's name here. So let's go to show. Let's look for a random title. OK, let's replace this with idea.title. And this will be idea.description. This will be.

And this will be idea description. This will be. Idea. Name. Sorry, idea, user name, so let's add that idea user name. And this will be the same as before, so idea created_at. diffForHumans. OK. Did I do that correctly? And that looks OK, but we might not have enough room here,

Generating Slugs for Ideas12:51

But I will focus on this later on, or maybe we can remove the number of comments here and move it maybe somewhere down here. OK, so the next thing I want to work on is make this number here. Use a slug instead. So if you remember, we created a slug in our table or a slug field. So right here and it's null right now. So it's not very hard to generate a slug given a title, but you do have to handle the case where the title is the same. And when that happens, you want to add a number to the end. So instead of implementing that ourselves, I'm going to make use of this package

And when that happens, you want to add a number to the end. So instead of implementing that ourselves, I'm going to make use of this package over here called Eloquent Sluggable. It's very easy to use. So let's go ahead and integrate it into our app. So let's go ahead and install this. You can read more about slugs here. And where's the installation right here? Okay. And you can publish the config if you want, but I don't need to do that.

Okay. And you can publish the config if you want, but I don't need to do that. So now we just have to use the Sluggable trait. So let's do that in our Idea model. So let's use Sluggable here. Okay. And that should import it. And we just have to add this sluggable method and give it a source. So in our case, since we have a field named title, this should work. So let's grab all of this.

So in our case, since we have a field named title, this should work. So let's grab all of this. Let's put it right here. And that should take care of it. It's automatically going to take a look at our title and generate a slug for it. And if there's any duplicates, it will append numbers to the end of them. So they're unique. So if I were to migrate fresh seed again, everything is the same. But if you look at our database now, as you see before, it was null.

everything is the same. But if you look at our database now, as you see before, it was null. But now there is a slug based on the title. And like I said, it does handle the case when there are duplicate titles and adds numbers to them. So now let's add the slug into our URL here. So instead of using the number, we want to use the slug. So how do we do that? So there, well, eight added a feature, which makes this really easy. And you can specify the column name you want to use for route model binding.

So there, well, eight added a feature, which makes this really easy. And you can specify the column name you want to use for route model binding. So here, idea, colon, in our case, we want to use the slug. So let's see if this works. So two should no longer work if I refresh this and it doesn't. But now if I refresh this, you'll see in the bottom left, it now goes to the slug and this should work. So there we go. So now we have our slug. And this should work.

So now we have our slug. And this should work. So there we go. It's now making use of the slug here. Actually, this is getting annoying. So I'm going to fix this and just make use of a firstName here because I actually think this should be just a username and those shouldn't be too long. For example, in the Laracasts form, it just shows the user's username here. And it's not too long, like I said. So let's change it to just show a firstName.

And it's not too long, like I said. So let's change it to just show a first_name. So I believe I can go to my UserFactory, which ships with Laravel and change this. So let's just change name to first_name and that should be shorter. Hopefully. Let's do this again. php artisan migrate --fresh --seed and back to our app. Let's go back here and let's check out the user's names. And yeah, it's much shorter now. Okay.

Adding Simple Pagination16:27

And yeah, it's much shorter now. Okay. One more thing I want to do here, and that's simple pagination. So right now I have 30 ideas, but if you wanted to paginate that, we can make use of Laravel's features. Now I might eventually switch to Livewire's pagination, but for now I'll just make use of default Laravel. So let's say we wanted 10 per page, 10 ideas per page. Let's do that. So in our IdeaController, instead of Idea::all, we can do Idea::simplePaginate

Let's do that. So in our IdeaController, instead of idea all, we can do idea, simplePaginate, simplePaginate, and let's give it a number here, say 10. And in our index blade, so let's put it after the container. Oh yeah. I forgot to break this down into its own component. We'll do that after the pagination. So after the ideas container, let's add a div here. Let's say I believe it's ideaLinks and that should add the pagination. And by default, it makes use of tailwind.css, which is what we're using here.

Let's say I believe it's Idea links and that should add the pagination. And by default, it makes use of Tailwind CSS, which is what we're using here. So it should look decent and maybe in the future we'll modify that. And we have an error here, Idea links. Sorry. It's Ideas links. Okay. And now we should have pagination. Yeah, we do. So yeah, let's add some padding on this or some margin, say my-8.

I'm just going to leave it for now since we're not even making use of Livewire yet, and we'll just separate it out into its own component when we start making use of Livewire and doing all the voting stuff here. So, yeah, I think that's a good place to break. Our ideas are now dynamic and coming from the database and our index page and our show page is correctly showing it from the database. So as always, let's go ahead and make a new page. As always, let's go ahead and make a commit. So let's git add, git commit. Actually, what episode is this?

So let's git add, git commit. Actually, what episode is this? Episode nine. Episode nine. Let's say Idea, model and migration.

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