Part 1: Laravel CRUD Blog (Blade)

Part 1: Laravel CRUD Blog (Blade)

Part 1 of a Laravel CRUD (Create, Read, Update, Delete) series, showing how to build a blog with blade

April 2019

CRUD operations are the basis for many websites and something which Laravel excels in.

In this series, I will be going through how to create a simple blog using Laravel. Here is the outline:

  • Part 1: Create the blog using Laravel and Blade templates
  • Part 2: Update the blog to provide a REST API
  • Part 3: Accessing and displaying content from the REST API with a decoupled front-end using Vue.js

The blog itself isn't anything complex, but it will go through many important aspects and features of Laravel.

If you want to code along with me, you will need to have a local PHP server running. You can follow my article here to get started with Homestead and create a fresh project.

Otherwise, you can run the finished code and see how it all works by following the instructions here:

Source Code

Getting started

The first step is to make a Model for the posts. We will also need a database Migration for the model to interact with, as well as a Controller to handle requests for the model.

Luckily, Laravel provides an excellent Command Line Interface called Artisan which allows us to generate all this (and much more), rather than doing everything manually.

To create these, SSH into the Virtual Machine and change directory to the code folder (if using Homestead):

We are now ready to generate what is needed.

The 'make:model' command will make the model, however adding '-mcr' will also create a Migration and a Controller.

The 'r' indicates that we want to create a Resource Controller. This removes alot of work when making a CRUD system by assigning all the desired routes automatically.

If it all went well you will see this:

Generating the Post Model, Migration and Resource Controller

These new files are found at:

  • Model: /app/Post.php
  • Migration: /database/migrations/TIMESTAMP_create_posts_table.php
  • Controller: /app/Http/Controllers/PostController.php

There is a small bit of configuration required in the Model and Migration files, but the majority of the time will be spent in the Controller.

Generating these files has actually accomplished a lot in the background as you will see further in the article.

Cleaning up

Before going any further, we should remove a couple of files which won't be used in this project and will just clutter it up, specifically relating to user registration.

Remove the two default User Migrations provided by Laravel (they have a timestamp of 2014, so the below will remove them both). Also remove the default 'Welcome' view for the homepage:

There is also a User API route which isn't needed. Open the file at '/routes/api.php' and remove the route (underneath the comments). This will prevent the route showing when we are listing all the routes.

To view all registered routes, run this:

A list of all routes

As you can see, we only have one route defined ('/'), for navigating to the homepage/root. Let's change that.

Mapping CRUD/Resource Routes

We need to assign routes which match up to the relevant methods on the Controller, which will then allow handling of requests.

Laravel makes this super easy. As we have previously indicated that our Post Model is a Resource, we can define all the routes we need with one line in '/routes/web.php'.

While we are here, lets change the default ('/') view to refer to the Post Controller, as the homepage will be listing the latest posts.

Change the contents of the file to:

List the routes again, and you will see that we now have all the routes needed for a CRUD system! 🎉

A list of all routes after defining the resource routes

Take a look at the Post Controller (/app/Http/Controllers/PostController.php), and you will see that all the routes match up with the methods Laravel has already generated. This has cut out a considerable amount of work.

Database Migrations

Next, we will move onto the database and define which fields we need for a blog post.

Open up the Posts Migration file at '/database/migrations'.

When working with databases, I find it useful to first write down all columns that will be needed and think about any special conditions. For a post, we will have:

  • Title: A string, with a max-length of 100 characters. This will need to be unique (each title can only be used once)
  • Content: A string, with a max-length of 2000 characters
  • Category: A string, with a max-length of 30 characters
  • Slug: A string, with a max-length of 200 characters. This also needs to be unique as it will be used in the URL to navigate to posts

Now that the fields are mapped out, add them to the 'up' method, which will be used to add the fields listed to the post database table:

All available column types can be found here.

Now, run the migrations to call the 'up' method and insert the new columns to the database:

Running the Database Migration

If you connect to the database you will see the new 'posts' table with the columns we specified, ready to accept data:

Empty database with the new columns shown

That's the initial setup done. Now it's time to move on to creating the forms and handling the requests.

Layout file

When working with Blade, it's important to use a 'layout' file. The contents of this file will carry across all views, thereby eliminating repeated code.

Create the layout file:


As usual, I'll be using Bulma for quick styling; I won't be focusing much on design here as it doesn't matter for this project.

The contents of the layout is basic HTML, with a few Blade directives thrown in. These are added via 'route()' to link to the routes previously defined, meaning that if the URLs ever change the links will continue to work. There is also a section for a notification, which will be handled later. Yielding 'content' will allow the insertion of content from other views into the layout.

Add this to the layout file:

One quick thing; Bulma doesn't come with any JavaScript. To get the mobile navigation to work, create a file at:


Add the following, and don't worry about looking through this code as it isn't in the scope of this article:

CRUD - Create

Time to move onto the good stuff! Before posts can be displayed we will need to create some, so this will be the first step.

Open up the PostsController and make this change to the 'create' method:

The means that when a user navigates to the route we have previously defined at /posts/create (remember, php artisan route:list will show all defined routes), the Controller will return a create view located in the /resources/views/posts folder. Create this folder and file:


Add the following, and I'll explain some bits after:

The above creates a HTML form with inputs for Title, Content and Category.

A few notes on the blade directives used:

  • @section('title', 'New Post'): Defines the page title, which is yielded in the layout
  • @extends('layout'): Extend/use the layout
  • @section('content') ... @endsection: Everything in here goes into the 'content' section of the layout
  • @csrf: This creates a hidden field with a unique token for each session, providing security against Cross-site request forgery
  • @include('partials.errors'): Includes an errors partial, which will be created next. This will show any errors returned if the form submission wasn't successful
  • old('field_name'): If the form submission wasn't successful this will add the data previously entered to the form. This means that the user won't have to re-enter everything each time they submit

Now is a good time to create the error partial. This is a reusable file which will be used for all forms. Create a 'partials' folder and add the errors file:


Add the following, which is checking if there are errors and displaying them if so:

Refresh the page at /posts/create and the form will be shown:

Create new post form

If the form is submitted at this point nothing will be shown as we haven't defined what should happen.

Look at the 'action' at the start of the form. A 'post' request is being sent on submission to ''. This relates to the 'store' method in the Post Controller.

I've added comments here to explain each part, but you can see how little code Laravel needs to deal with requests:

At the top of the Controller where the 'use' statements are, add this one so we can use a Laravel Helper to create slugs:

This is all looking great so far!

I'm using Mass-assignment here to save the entire request in one go. To enable this, the 'fillable' fields need to be set in the Model file:


I also want to link to posts using a unique 'slug' rather than the default ID. Add this as well and we are done with this file:

The create form is now ready to use!

When the form is submitted, the validation rules set are checked against the data received. If it fails, the relevant errors will be shown and the user's input will be retained in the form fields. On success, a new post will be added to the database.

You can see a GIF of the form and validation in action here.

You probably noticed that when the post was created the user is redirected to a blank page at '/posts/slug', which is the correct URL. There is no view defined for viewing the individual post, which brings us to the next part of the CRUD system.

CRUD - Read

The 'Read' part is pretty easy as all it involves is displaying the content.

After form submission, the user is redirected to the '' route, which relates to the 'show' Controller method. Change the method to this in the Post Controller:

This view now needs to be created at:


Add the following to it:

I've included a partial here named 'summary', as the display of the individual post is going to be reused on the homepage.

Create the partial at:


And add the code to display the Post details:

A few notes about some Blade directives and other bits I haven't covered yet:

  • $post->field_name: This allows access to the the current Post data which was passed through from the 'show' method in the Post Controller previously
  • {{ $post->created_at->diffForHumans() }}: Laravel comes with Carbon built in to handle dates. 'diffForHumans' is a method which is being used to format the 'created_at' into a readable string
  • {!! nl2br(e($post->content)) !!}: The default syntax in Blade to access data ({{ field }}) will strip whitespace, which will need to be kept when working with a textarea. This workaround still applies validation but runs the output through nl2br to insert line-breaks
  • @method('delete'): The 'delete' action isn't supported by forms. This creates a hidden field for Laravel, which tells it that the form is actually submitting a 'delete' request rather than 'post'

Give the post a refresh and we can now see the post details!

View post

Everything looks as it should here. The date formatting is working, everything is being displayed, and the notification we added earlier in the layout file is working.

Now that the display of a single post is working it's time to show a list of the most recent posts. This relates to the 'index' method of the Post Controller, so let's update it:

Then create the relevant view:


Add the following code, which loops through each post passed to the view and displays a post summary:

CRUD - Update

The next bit of functionality to add to the blog is to allow editing/updating of posts. Thankfully, this is very similar to the process for creating a post, so there isn't much to explain here. Change the 'edit' method in the Post Controller, which is responsible for providing the form view:

Create the new view at:


This form is very similar to the 'create' form, except it has a hidden field to indicate that this is sending a 'patch' request to update the Post:

Now to handle the request for when the update is made via the form. This is handled by the 'update' method in the Post Controller, which should be the below:

Click the 'edit' button on one of the posts, change the content and update it and the changes will be reflected after you have been redirected.

Editing a post

CRUD - Delete

And now onto the final piece of the puzzle, and one of the easiest! You should see by now how quick it is to work with these requests when the initial setup has been handled.

Update the 'destroy' method of the Post Controller to this:

Click the 'delete' button on any of the posts and it will be removed from the blog, with a notification being shown to confirm this:

Deleting a post

Finishing up

So there you have it; a basic CRUD blog using Laravel and Blade. Hopefully this will help clear up some things or make you want to get started working with Laravel.

You can get the full source code for the article below:

Source Code

Want to hire me for a project, or to fix something on your website?

Get in touch 😀