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

App Idea Overview0:00

For this mini-series, let's work on a little snippet-slash-forking application. It'll give you some good workflow examples, and then also I can leave you with some steps to take on your own at the end. So yeah, as you can imagine, you can create a snippet, maybe a JavaScript ECMAScript 2015 class syntax. And we could do something like this, class MyClass, like so, and we create our snippet, and we get the highlighting here. But then somebody else, if they want, they can review it, and they can fork it, and then change it. So maybe they want to show how to add a constructor here. this.name equals name, create it, and now we have theirs. And if we click on the original, we can see, alright, here's the snippet, but also it has been quote-unquote forked one time here, and here's the fork, and of course we can go back. So this is kind of a basic, simple app, but again, it'll give us some good educational things to work through.

Project and Database Setup0:48

and here's the fork, and of course we can go back. So this is kind of a basic, simple app, but again, it'll give us some good educational things to work through. Now, as always, we'll start from scratch. Let's say laravel new snippets, and I am going to add the --dev flag to pull in the 5.4 branch of Laravel. So we can be on the cutting edge. Okay, so let's cd in there, and open this up in Sublime. Now, first things first, let's set up a little database. SQLite is totally fine for this, so we can get rid of all of these other settings, because the defaults will be fine. Next, I'm going to touch database/database.sqlite, and then php artisan migrate. Okay.

Creating Snippet Model1:23

Next, I'm going to touch database/database.sqlite, and then migrate the database. Okay. Next, we're going to work with snippets. So maybe we could make a model called Snippet, and then I will add the --migration flag here to also create a migration. Let's take a look at that. Create snippets table. Okay, so for this series, we're not going to worry about authentication and associating a Snippet with a User, but that will be an assignment I give you at the end. So with that in mind, let's stick with a string for the heading or the title. Why don't we just call it title?

So with that in mind, let's stick with a string for the heading or the title. Why don't we just call it title? Next, a text column for the body of the snippet, and that will be the snippet itself. And then finally, we know that a snippet can optionally fork another snippet. So it sounds like we need some reference there. So for example, if I create a new snippet, maybe I can say, well, this snippet was forked from that snippet ID. So this can be an integer, and we'll call it forkedId maybe, but it can be null, like I said. Okay, so let's go ahead and migrate our database, and we have our snippet table. Next, what else? Why don't we go to our routes/web.php file, and we'll set up some routing here.

Defining Routes and Controller2:35

Next, what else? Why don't we go to our routes/web.php file, and we'll set up some routing here. So we'll say when you get the home page, that's going to load our SnippetsController and an index method. Also, while we're at it, let's give it a name of home, and that way we can do things like return redirect('home') in our controllers. Okay, what else? Let's do a couple while we're here. If you visit snippets/{id}, that should load SnippetsController and then a show method. Next, how about one to create a snippet? Okay, create.

Next, how about one to create a snippet? Okay, create. We will need one to store a snippet, so if you post to snippets, that'll hit SnippetsController at store. And I think we'll add one more, but this should get us started. So view all snippets, create a new snippet, view one snippet, and then store a new snippet. Let's go ahead and create that controller. Okay, let's switch over there. And like I said, we'll have an index method. We will have a method to create a new snippet. We will need one to show an existing snippet.

We will have a method to create a new snippet. We will need one to show an existing snippet. So we know we're going to use route model binding there. So for example, right here, Laravel will know to automatically track down the snippet that has that ID. So for example, snippets/1 will track down the snippet with an ID of one and give us the Eloquent model. Let's go ahead and import that. Okay, what else? We will need one to store a new snippet. All right, so why don't we get started? We're going to load some views here, like snippets.index, and then snippets.create,

All right, so why don't we get started? We're going to load some views here, like snippets.index, and then snippets.create, and then snippets.show, where we will pass through the snippet. Sound good? Okay. So let's go to our resources folder into views, and welcome, we're not going to use that at all. So let's delete it and create a couple new ones. So snippets, we're going to need index.blade.php. We'll need another one for show.blade.php, and then another one for create.blade.php. Okay.

Building Layout with Components4:45

We'll need another one for show, and then another one for create. Okay. Next, we're going to need a layout file, right? So resources/views/layouts, and we're going to use the new components feature in Laravel 5.4. And if you're watching this and Laravel 5.4 isn't quite out just yet, this may be the first time you've seen it. Now, traditionally with Laravel, you might yield a content section, and you can still do this. It hasn't been removed or anything. But if we want to use components instead, what we could do is echo out the slot, whatever that might be. And then within our views, for example, we could say I'm going to have a component here. And in this case, the component is layout.

And then within our views, for example, we could say I'm going to have a component here. And in this case, the component is layout. So we give it the name just as if you were doing view or something like that. So here's our components. And then within here, whatever I slot between these two tags, so to speak, will automatically be saved as slots. So we'll spit all of that content out right here. And then, for example, if we later had a title or something like that, yeah, you could just say right here the slot called title. And, yeah, that's just going to correspond to what the variable name is. That will be foobar and slots. And now right here in our component, we'll spit out the title, and then we'll spit out the default slot text.

That will be foobar and slots. And now right here in our component, we'll spit out the title, and then we'll spit out the default slot text. If you're familiar with view or view components, this is going to feel very similar to you. And it's going to take some time to grow on you, but I think you'll like it. Anyways, so now we will list all snippets. Okay, so let's copy and paste this. And then we'll have one more for showing the snippet. So does that all make sense? If we visit the home page, this is the view we load. We're referencing the layout component that looks like this.

If we visit the home page, this is the view we load. We're referencing the layout component that looks like this. And we don't need that. We'll just say snippet. And right now we're just going to have a single slot, and we're going to nest all of this content right there. But you know what? Why don't we wrap this within a container div, and then I'm going to import a little CSS framework just to make things a bit more attractive. So I will paste that in here. We are referencing the Bulma CSS framework just through Cloudflare. Okay, so why don't we give this a shot?

We are referencing the Bulma CSS framework just through Cloudflare. Okay, so why don't we give this a shot? I'm using Laravel Valet, which means I can go to snippets.dev. And there we go. If we view the source, we can see that it is being inserted right there. Okay, great. So now why don't we set up a quick little header? And we can do that within our layout file. Bulma includes some nice CSS styling if we have a section called hero. And we're going to have it be medium height.

Okay, come back, refresh. Looks good enough. The only remaining thing is let's add a button here. Maybe something like this. snippets/create and createSnippet. Okay, let's give that some styling. A class of button. Okay, so when we click on this, it takes us to the page to create a snippet. And we can tackle that now. Let's go to our create view.

Creating and Saving Snippets8:39

And we can tackle that now. Let's go to our create view. And we'll say let's have a title here is one. And we'll say I want a new snippet. A little big. Let's get rid of that entirely. Okay, better. So, yeah, we're going to need a form here, right? And it's going to submit to snippets. And the method will be POST.

And it's going to submit to snippets. And the method will be post. So if we think about it, we need an input for the title. We should give that a name as well. And then we'll also need a textarea for the body of the snippet. Okay, let's give this a refresh. Yeah. Finally, I need a button down here. FormButton. I have a few snippets to help out.

Form button. I have a few snippets to help out. Create snippet. Or how about publishSnippet. Refresh. And there we go. So now let's see what's going to happen here. Well, first, of course, I do need to add the csrf_field. For any form that you're posting or submitting to the server, you should make sure you add this.

For any form that you're posting or submitting to the server, you should make sure you add this. But anyways, it'll post to /snippets. And in our routes file, if we receive that, we call SnippetsController at store. So now here is where we can save the snippet. Something like this. Snippet::create(). And we'll say the title is whatever you gave us. And then the body, once again, is whatever you gave us. Now we should add validation here.

And then the body, once again, is whatever you gave us. Now we should add validation here. I'll set a placeholder for that. And then once we're done, we will redirect to the home page. But this isn't going to work, is it? Let's try it. Publish. And, yeah, we get a mass assignment exception. And that's because here we haven't updated our Snippet class to reference any fillable fields.

And that's because here we haven't updated our Snippet class to reference any fillable fields. And as we've discussed at Laracasts many times, this is something LayerFill does out of the box. So what you could do is set your fillable fields and be explicit. If you trust yourself, then you can say $guarded equals an empty array. Or another option, a little trick here, if you know that you'll always be smart and you're never just going to pass, for example, request()->all(), where you're never just going to blindly pass everything to this method.

about mass assignment vulnerabilities. So why don't we do this? Why don't we say php artisan make:model just called Model. This will be our application's parent model. And we're going to save that as Eloquent so we don't have any overlap. There we go. So now any of your models can just extend your application model. Now things like this can go here, and they will cascade down to all of the classes that extend it. Make sense?

and they will cascade down to all of the classes that extend it. Make sense? Let's give this another shot. Let's come back, refresh, and once again we'll say es2015 class syntax, where we say class User, and we will publish it. So we created the snippet. It redirected to the home page, but we're not yet displaying that. That can be our next step.

Listing Snippets on Home12:07

It redirected to the home page, but we're not yet displaying that. That can be our next step. In our index method, we could say fetch the latest snippets. So get all snippets in descending order, and I'll pass that through. Let's switch over to that, and we'll say how about this? If count snippets, then we'll say for each snippets as snippet, maybe we'll put this within an article,

then we'll say for each snippet as snippet, maybe we'll put this within an article, and maybe we'll give it a class of snippet where we have an h4, and this will be a link to the given snippet that we can identify by its ID. Okay, so snippet title, close that out, close our h4. Let's see how we're doing. Refresh. Whoops, line 14.

Refresh. Whoops, line 14. Oh yeah, of course. End foreach, end if. Okay, so we can get rid of this, and we have our snippet. Next, let's do this. We'll say within <pre><code> tags, let's echo out the snippet body. Come back and give that a refresh.

let's echo out the snippet body. Come back and give that a refresh. Okay, so that's starting to take shape. You can create a snippet. We'll say short object syntax, return, name, age, location, publish it, and there we go. Maybe we should add a little bit of spacing there. So you know what? Let's do this.

So you know what? Let's do this. Let's go to our layout file and import. We're not going to compile anything, so I will just reference app.css, and Laravel should include one out of the box that contains all of the bootstrap stuff compiled down. I'm just going to delete it entirely, and instead we'll say for each of those articles, let's just give it some margin bottom of about 2ms,

and instead we'll say for each of those articles, let's just give it some margin bottom of about 2ms, and then maybe a border bottom of 1px dashed gray. Okay, so if we come back and give that a refresh. Okay, so we see the border here. Now, what's happening is I think we have a background color on the pre-tag that Bulma's applying. Yeah, so you know what? Why don't we just get rid of that? Let's come back to app.css.

Why don't we just get rid of that? Let's come back to app.css. Pre-tags should have a background of none. Okay, back to Chrome, refresh. Yeah, that looks good to me. So now we can view all snippets. We don't yet have syntax highlighting, but that's okay. We'll come back to it. Next, I'd like to view a specific snippet. So that means we're going to load.

Snippet Show Page14:45

Next, I'd like to view a specific snippet. So that means we're going to load. If we go back to our resources/views, it's going to load our show view. Now, once again, we're going to have a title section for the title of the snippet. Refresh. There it is. We will spit out the snippet. Come back, refresh. There it is.

Starting Forking Workflow15:30

with the body from the previous one. That'll be a nice and simple way to do this. So, hmm, how can we do this? Why don't we wrap this within a div with a class of isflex, which basically labels a container as display flex. That way I can do things like this. I can say we'll have an anchor tag here to create a snippet, and we'll call it fork me.

to create a snippet, and we'll call it fork me. But I want that to be all the way to the right here. So what I can do is basically tell this element to flex itself, and now it's going to take up as much space as it possibly can. Okay, let's do this. I want a class called flex, but I don't think that's included with Bulma,

I want a class called flex, but I don't think that's included with Bulma, so that'll be another one we add here. Flex will be flex1. There we go. Now, though, if we click on this, it's just going to link to the page to create a new snippet. Why don't we think about this? Instead, maybe that link will go to snippets,

If we click on this, it's to snippets id fork, which does not exist. Okay, so let's do this now. If you visit snippets and id fork, well, you know what? We could do something like a ForksController, but I think we still might be able to get away with SnippetsController. Let's think about this.

with SnippetsController. Let's think about this. If this will load SnippetsController at create, now, that could accept a Snippet, and we're going to have two different scenarios. One, let's come back. If we click on this Snippet, that'll just be an empty object, an empty Eloquent object. So, for example, if we die and dump the snippet,

an empty Eloquent object. So, for example, if we die and dump the snippet, refresh. Yeah, it's just a snippet that has not been saved or persisted. However, if we click on one of these and we fork it, well, behind the scenes, HTML is going to find us the snippet with an ID of two, and we can get that attribute.

HTML is going to find us the snippet with an ID of two, and we can get that attribute. So with that in mind, we're going to receive it, pass it through to the view, and then within the create view, here's what we could do. We could set the default value to snippetTitle, and then the same thing here for the text area, snippetBody.

We will fork this one, and now we can start with that structure. But this still won't be enough because, yes, I can change this. Maybe we accept a constructor here and publish it. And, yes, we'll see the original as well as the forged version, but right now we haven't created a relationship between this one and the original.

but right now we haven't created a relationship between this one and the original. So we'll tackle all of that in the second half of this two-part series. I'll see you then.

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