This Is Your Quintessential Guide to Creating a Blog With Laravel
Mark "Awesomarky" Enriquez
Globally Competitive Software Engineering, Web Design, Branding and Digital Marketing
People start a blog for different reasons. Some want to tell personal stories about travel or fashion while others want to share their passion for a certain craft to people who have the same interest. Blogging is also becoming a favorite marketing strategy for many businesses. In fact, it is a go-to content marketing strategy for 53% of marketers.
But how exactly do you create a blog? Laravel is a preferred framework for a lot of blog developers because it’s easy to use, pocket-friendly and offers a wide range of layouts to choose from. In this tutorial, we will show you the steps to creating a blog using the Laravel PHP framework:
Installing Laravel
Since Laravel uses Composer for its dependencies, your first order of business should be to download the Laravel installer through Composer by running the following command:
$ composer global require “laravel/installer=~1.1"
To make sure that Laravel is found once you run the command on your terminal, don’t forget to add this line to your alias:
laravel = ~/.composer/vendor/bin/laravel
After that line is added to your PATH, run the following command from your terminal:
$ laravel new blog
$ cd blog
The Laravel new command will then create a new installation on your specified directory. For Laravel new blog, a directory named blog will be created and this will contain a fresh Laravel installation with all dependencies. After that blog folder is created, try to run this command:
$ php artisan serve
Try visiting https://localhost:8000/ and you will see the Laravel Welcome page. Once Laravel is successfully installed, you can now proceed to git commit/push. To push to github, you need to create this repo first:
$ git init
$ git remote add origin https://github.com/user/repo.git
$ git add .
$ git commit -m “first commit”
Then, you can add Way Generator to the project by editing your project’s composer.json file so it requires way/generators. Add this line:
“require-dev”: {
“way/generators”: “~2.0"
}
Once that’s added, update your Composer from the terminal by running this command:
$ composer update —dev
Once this task is complete, don’t forget to add the service provider by opening config/app.php and adding a new item to the providers array with this command:
‘Way\Generators\GeneratorsServiceProvider’
After that’s done, you can run the php artisan command from the terminal to view the new generate commands.
The Environment Setup
First, run this command on the terminal:
$ php artisan env
Then, you will see this:
Current application environment: production
You need to change that into local environment by running the command on the terminal:
$ hostname
Then, add your local hostname to bootstrap/start.php on line 29 by removing default homestead. Run this command after to check your environment:
$ php artisan env
You should be seeing this result:
Current application environment: local
Database Setting
Next, you have to edit database setting in app/config/local/database.php. After editing, commit it by running this command:
$ git add .
$ git commit -m “Added Devlopment Setting”
$ git push origin master
Blog Admin
To migrate your user table through Way Generator, just run this command:
$ php artisan generate:migration create_users_table —fields=”username:string, password:string,email:string, remember_token:string”
$ php artisan migrate
You can then add your username, password, email and remember_token to your user table migration.
Seeding
Run this command to run user seeding:
$ php artisan generate:seed user
We will not be using Faker from Way Generator because it only allows one seeding, so edit your UserTableSeeder with the following code block:
<?php
class UserTableSeeder extends Seeder {
public function run()
{
DB::table(‘users’)->delete();
User::create(array(‘username’ => ‘admin’, ‘password’ => Hash::make(‘admin’), ‘email’ => ‘[email protected]’));
}
}
Remove the comment from app/database/seeds/DatabaseSeeder.php online 14 like the following:
$this->call(‘UserTableSeeder’);
Now, run the command $ php artisan db:seed where you should see this message: Seeded: UserTableSeeder. Git commit/push this by running the command on the terminal:
$ git add .
$ git commit -m “Added User Table Seed”
$ git push origin master origin
Views
Moving to the views, we need to create a main.blade.php in app/views/layout:
<!DOCTYPE html>
<html>
<head>
<title>Laravel | BLOG</title>
<!— Latest compiled and minified CSS →
<link rel=”stylesheet” href=”https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<!— Optional theme →
<link rel=”stylesheet” href=”https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap-theme.min.css">
</head>
<body>
@yield(‘content’)
<script src=”https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!— Latest compiled and minified JavaScript →
<script src=”https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
</body>
</html>
Authentication Route
To add authentication route, add these lines to routes.php:
Route::get(‘/admin’, ‘AuthController@create’);
Route::post(‘/admin’, ‘AuthController@store’);
Once that’s done, let’s move to AuthController by running this command:
$ php artisan generate:controller AuthController
Then, remove all other methods except create and store from AuthController.
Login View
To create login view, run this command:
@extends(‘layout.main’)
@section(‘content’)
<style type=”text/css”>
.login-form {
width: 248px;
margin: 0 auto;
}
</style>
<div class=”container”>
{{ Form::open(array(‘/admin’, ‘role’ => ‘form’, ‘class’ => ‘login-form’)) }}
<h1>Please Login</h1>
<div class=”form-group”>
{{ Form::label(‘email’, ‘Email Address’) }}
{{ Form::text(‘email’, ‘’,array(‘class’ => ‘form-control’, ‘placeholder’ => ‘Enter email’)) }}
</div>
<div class=”form-group”>
{{ Form::label(‘passowrd’, ‘Password’) }}
{{ Form::password(‘password’, array(‘class’ => ‘form-control’, ‘placeholder’ => ‘Password’)) }}
</div>
{{ Form::submit(‘Sign in’, array(‘class’ => ‘btn btn-primary’)) }}
{{ Form::close() }}
</div>
When you’re done creating index view, let’s move on to AuthController create method by editing from AuthController.php:
public function create()
{
return View::make(‘admin.index’);
}
When you visit https://localhost:8000/admin, you should see a log in form.
On AuthController.php:
public function store()
{
if ($this->isPostRequest()) {
$validator = $this->getLoginValidator();
if ($validator->passes()) {
$credentials = $this->getLoginCredentials();
if (Auth::attempt($credentials)) {
Session::flash(‘message’, “Welcome Sir!”);
return Redirect::to(“/”);
}
return Redirect::back()->withErrors([
“invalid_credential” => [“Credentials invalid.”]
]);
} else {
return Redirect::back()
->withInput()
->withErrors($validator);
}
}
return View::make(“admin.index”);
}
//Check user’s post request
protected function isPostRequest()
{
return Input::server(“REQUEST_METHOD”) == “POST”;
}
//Validate
protected function getLoginValidator()
{
return Validator::make(Input::all(), [
“email” => “required|email”,
“password” => “required”
]);
}
//Get Login Credentials
protected function getLoginCredentials()
{
return [
“email” => Input::get(“email”),
“password” => Input::get(“password”)
];
}
The first code on the code block was to check if it’s post request or not. If it is, we validate and log in. Once you log in and there are no errors, edit your view like the following:
@extends(‘layout.main’)
@section(‘content’)
<style type=”text/css”>
.login-form {
width: 248px;
margin: 0 auto;
}
.container {
padding: 10px;
}
</style>
<div class=”container”>
{{ Form::open(array(‘/admin’, ‘role’ => ‘form’, ‘class’ => ‘login-form’)) }}
<h1>Please Login</h1>
@if(!empty($errors->first(‘invalid_credential’)))
<div class=”alert alert-danger”>{{ $errors->first(‘invalid_credential’) }}</div>
<div class=”form-group”>
@if(!empty($errors->first(“email”)))
<div class=”alert alert-danger”>{{ $errors->first(“email”) }}</div>
{{ Form::label(‘email’, ‘Email Address’) }}
{{ Form::text(‘email’, ‘’,array(‘class’ => ‘form-control’, ‘placeholder’ => ‘Enter email’)) }}
</div>
<div class=”form-group”>
@if(!empty($errors->first(“password”)))
<div class=”alert alert-danger”>{{ $errors->first(“password”) }}</div>
{{ Form::label(‘passowrd’, ‘Password’) }}
{{ Form::password(‘password’, array(‘class’ => ‘form-control’, ‘placeholder’ => ‘Password’)) }}
</div>
{{ Form::submit(‘Sign in’, array(‘class’ => ‘btn btn-primary’)) }}
{{ Form::close() }}
</div>
After updating your view, it should show an error prompt when you validate something.
- Logout View
Add this line to your route to start with logout view:
Route::get(‘/admin/logout’, ‘AuthController@logout’);
Then, add the following code block:
public function logout()
{
Auth::logout();
Session::flash(‘message’, “Logout success sir!”);
return Redirect::to(‘/’);
}
To git commit/push the login and logout methods, run this command:
$ git add .
$ git commit -m “Login & Logout Added”
$ git push origin master
- Blog
For the admin blog part, start by running this command to generate the blog post resource:
$ php artisan generate:resource post —fields=”title:string, body:text”
Then, add this code block to routes.php:
Route::resource(‘admin/posts’, ‘PostsController’);
Now, if you visit https://localhost:8000/admin/posts, you will see a blank screen, so we need to add some design. Add this code block to PostController’s index method first:
return View::make(‘posts.index’);
Then, add the following code block to app/views/post/index.blade.php:
@extends(‘layout.main’)
@section(‘content’)
<style type=”text/css”>
</style>
@include(‘layout.adminnav’)
<div class=”container”>
<div class=”col-md-12">
<div class=”pull-right”>
<a href="/admin/posts/create"><div class="btn btn-success">Add New Blog Post</div></a>
</div>
<table class=”table”>
<thead>
<tr>
<th>ID</th>
<th>BLOG TITLE</th>
<th>EDIT BLOG</th>
<th>DELETE BLOG</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Hello world</td>
<td><div class=”btn btn-primary”>Edit Blog</div></td>
<td><div class=”btn btn-danger”>Delete Blog</div></td>
</tr>
</tbody>
</table>
</div>
</div>
Then, add this code to layout/adminnav.blade.php:
<nav class=”navbar navbar-default” role=”navigation”>
<div class=”navbar-header”>
<button type=”button” class=”navbar-toggle” data-toggle=”collapse” data-target=”#bs-example-navbar-collapse-1">
<span class=”sr-only”>Toggle navigation</span>
<span class=”icon-bar”></span>
<span class=”icon-bar”></span>
<span class=”icon-bar”></span>
</button>
<a class=”navbar-brand” href=”/”>Laravel BLOG</a>
</div>
<div class=”collapse navbar-collapse”>
<ul class=”nav navbar-nav”>
<li><a href=”/”>BLOGS</a></li>
</ul>
@if(Auth::check())
<ul class=”nav navbar-nav navbar-right”>
<li><p class=”navbar-text pull-right”>Signed in as <a href=”/admin/posts” class=”navbar-link”>{{ Auth::user()->username }}</a></p></li>
<li><a href=”/admin/logout”>Logout</a></li>
</ul>
<ul class=”nav navbar-nav navbar-right”>
<li><a href=”/admin”>Sign in</a></li>
</ul>
</div>
</nav>
Now, when you visit https://localhost:8000/admin/posts, you will see a dashboard with a list of blogs and the options to edit or delete them. The design of this page will depend on your preferences.
- Create View
To start designing create view, add this code block to app/views/posts/create.blade.php:
@extends(‘layout.main’)
@section(‘content’)
<style type=”text/css”>
</style>
@include(‘layout.adminnav’)
<div class=”container”>
<div class=”col-md-12">
<h1>Write Your Post Here</h1>
{{ Form::open(array(‘url’ => ‘/admin/posts’, ‘role’ => ‘form’)) }}
<div class=”form-group”>
@if(!empty($errors->first(‘title’)))
<div class=”alert alert-danger”>{{ $errors->first(‘title’) }}</div>
{{ Form::label(‘title’, ‘Post Title’) }}
{{ Form::text(‘title’, $value = null, array(‘class’ => ‘form-control’, ‘placeholder’ => ‘Your Blog Post Title’)) }}
</div>
<div class=”form-group”>
@if(!empty($errors->first(‘body’)))
<div class=”alert alert-danger”>{{ $errors->first(‘body’) }}</div>
{{ Form::label(‘body’, ‘Blog Body/Content’) }}
{{ Form::textarea(‘body’, $value = null, array(‘class’ => ‘form-control’, ‘rows’ => ‘7')) }}
</div>
{{ Form::submit(‘Publish Your Blog Post’, array(‘class’ => ‘btn btn-default’)) }}
{{ Form::close() }}
</div>
</div>
Next, add this to store method:
public function store()
{
$rules = array(
‘title’ => ‘required’,
‘body’ => ‘required’,
);
$validator = Validator::make(Input::all(), $rules);
// process the login
if ($validator->fails()) {
return Redirect::to(‘/admin/posts/create’)
->withErrors($validator)
->withInput(Input::except(‘password’));
} else {
// store
$blog = new Post;
$blog->title = Input::get(‘title’);
$blog->body = Input::get(‘body’);
$blog->save();
// redirect
Session::flash(‘message’, ‘Successfully posted your blog!’);
return Redirect::to(‘/admin/posts’);
}
}
In the store method, we created a validation that if you fail to create a post, you will be redirected back to /admin/posts. If your post was successfully created, a success flash message should appear by adding this code to app/views/posts/index.blade.php:
@if (Session::has(‘message’))
<div class=”col-md-12">
<div class=”alert alert-info”>{{ Session::get(‘message’) }}</div>
</div>
To edit your index method, add this code block:
public function index()
{
$blogs = Post::orderBy(‘id’, ‘DESC’)->paginate(10);
return View::make(‘posts.index’, compact(‘blogs’));
}
Then, remove your admin/index hard-coded tbody and replace it with this code block:
<tbody>
@foreach($blogs as $blog)
<tr>
<td>{{ $blog->id }}</td>
<td>{{ $blog->title }}</td>
<td><a class=”btn btn-default” href=”{{ URL::to(‘admin/posts/’ . $blog->id) }}”>View this blog! </a></td>
<td><a class=”btn btn-primary” href=”{{ URL::to(‘admin/posts/’ . $blog->id . ‘/edit’) }}”>Edit Blog</a></td>
<td>
{{ Form::open(array(‘url’ => ‘admin/posts/’ . $blog->id)) }}
{{ Form::hidden(‘_method’, ‘DELETE’) }}
{{ Form::submit(‘Delete this Blog Post’, array(‘class’ => ‘btn btn-danger’)) }}
{{ Form::close() }}
</td>
</tr>
</tbody>
For your delete method, add this code block:
public function destroy($id)
{
$post = Post::find($id);
$post->delete();
// redirect
Session::flash(‘message’, ‘Successfully deleted!’);
return Redirect::to(‘/admin/posts’);
}
Then, add this code block to PostController for your edit method:
public function edit($id)
{
$post = Post::find($id);
return View::make(‘posts.edit’)
->with(‘post’, $post);
}
Next, edit app/view/posts/edit.blade.php:
@extends(‘layout.main’)
@section(‘content’)
@include(‘layout.adminnav’)
<div class=”container”>
<div class=”col-md-12">
<h1>Edit {{ $post->title }}</h1>
{{ Form::model($post, array(‘route’ => array(‘admin.posts.update’, $post->id), ‘method’ => ‘PUT’)) }}
<div class=”form-group”>
@if(!empty($errors->first(‘title’)))
<div class=”alert alert-danger”>{{ $errors->first(‘title’) }}</div>
{{ Form::label(‘title’, ‘Post Title’) }}
{{ Form::text(‘title’, $value = null, array(‘class’ => ‘form-control’, ‘placeholder’ => ‘Your Blog Post Title’)) }}
</div>
<div class=”form-group”>
@if(!empty($errors->first(‘body’)))
<div class=”alert alert-danger”>{{ $errors->first(‘body’) }}</div>
{{ Form::label(‘body’, ‘Blog Body/Content’) }}
{{ Form::textarea(‘body’, $value = null, array(‘class’ => ‘form-control’, ‘rows’ => ‘7')) }}
</div>
{{ Form::submit(‘Publish Your Blog Post’, array(‘class’ => ‘btn btn-default’)) }}
{{ Form::close() }}
</div>
</div>
After that, add this code block for your update method:
public function update($id)
{
$rules = array(
‘title’ => ‘required’,
‘body’ => ‘required’
);
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
return Redirect::to(‘/admin/posts/create’)
->withErrors($validator)
->withInput(Input::except(‘password’));
} else {
// store
$blog = Post::find($id);
$blog->title = Input::get(‘title’);
$blog->body = Input::get(‘body’);
$blog->save();
// redirect
Session::flash(‘message’, ‘Successfully updated your blog!’);
return Redirect::to(‘/admin/posts’);
}
}
To show blog post for admin, add this code:
public function show($id)
{
$post = Post::find($id);
return View::make(‘posts.show’)
->with(‘post’, $post);
}
Then, find post with para ID and pass that variable to posts.show view. Add this code block to app/views/posts/show.blade.php:
@extends(‘layout.main’)
@section(‘content’)
@include(‘layout.adminnav’)
<div class=”container”>
<div class=”col-md-12">
<h1>{{ $post->title }}</h1>
<span>Submitted in {{ date(“F j, Y, g:i a”, strtotime($post->created_at)) }}</span>
<p class=”lead”>
{{ $post->body }}
</p>
</div>
</div>
- Route
To edit your route, add this code block:
Route::get(‘/’, ‘HomeController@showWelcome’);
Route::get(‘/admin’, ‘AuthController@create’);
Route::post(‘/admin’, ‘AuthController@store’);
Route::group(array(‘before’ => ‘auth’), function()
{
Route::get(‘/admin/logout’, ‘AuthController@logout’);
Route::resource(‘admin/posts’, ‘PostsController’);
});
Routes will now be seen when a user has logged in. We also need to edit on app/filter.php where you should replace filter.php line 44 with this code block:
return Redirect::guest(‘admin’)->withErrors([
“invalid_credential” => [“Please login first!”]
]);
To git commit/push everything, add this:
$ git add .
$ git commit -m “Finished Blog Post CRUD”
$ git push origin master
- User
We have two goals for the user part of the blog, to show all the posts and to allow users to comment on these posts. Let’s start with showing all blog posts to our homepage by replacing this code:
Route::get(‘/’, ‘HomeController@showWelcome’);
With this code block:
Route::get(‘/’, ‘HomeController@showWelcome’);
Route::get(‘/blog/{id}’, ‘HomeController@showBlogDetail’);
Then, edit your HomeController’s showWElcome method with this:
public function showWelcome()
{
$blogs = Post::paginate(10);
return View::make(‘home’, compact(‘blogs’));
}
Add the following code block to edit home design on home.blade.php on view folder:
@extends(‘layout.main’)
@section(‘content’)
@include(‘layout.adminnav’)
<div class=”container”>
<div class=”col-md-12">
<div class=”panel panel-default”>
@foreach($blogs as $blog)
<div class=”panel-body”>
<a href=”/blog/{{ $blog->id }}”><h1>{{{ $blog->title }}}</h1></a>
<span>Submitted in {{ date(“F j, Y, g:i a”, strtotime($blog->created_at)) }}</span>
</div>
</div>
<div class=”pull-right”>{{ $blogs->links(); }}</div>
</div>
</div>
In that code block, there is a link to the title so when a reader clicks on that link, the post will be displayed. Next, let’s edit your showBlogDetail method, add this code:
public function showBlogDetail($id)
{
$blog = Post::find($id);
return View::make(‘blogdetail’, compact(‘blog’));
}
Then create blogdetail.blade.php with this code block:
@extends(‘layout.main’)
@section(‘content’)
@include(‘layout.adminnav’)
<div class=”container”>
<div class=”col-md-12">
<div class=”panel panel-default”>
<div class=”panel-body”>
<h1>{{ $blog->title }}</h1>
<span>Submitted in {{ date(“F j, Y, g:i a”, strtotime($blog->created_at)) }}</span>
<p class=”lead”>{{ $blog->body }}</p>
</div>
</div>
</div>
</div>
To git commit/push everything, run this command on the terminal:
git add .
git commit -m “Blog & Blog Detail”
git push origin master
Now, to generate migration of comments, run this command from your terminal:
$ php artisan generate:migration create_comments_table —fields=”name:string, post_id:string, comment:text”
Then, run this command to migrate:
$ php artisan migrate
To generate the comment model, run this command on your terminal:
$ php artisan generate:model Comment
Then, run this command to generate CommentController:
$ php artisan generate:controller CommentController
After that, remove all the generated method from CommentController by adding this code block at the end of blog detail view:
<div class=”col-md-12">
{{ Form::open(array(‘url’ => ‘/blog/comment/'$blog->id, ‘role’ => ‘form’)) }}
<div class=”form-group”>
@if(!empty($errors->first(‘name’)))
<div class=”alert alert-danger”>{{ $errors->first(‘name’) }}</div>
{{ Form::label(‘name’, ‘Your Name’) }}
{{ Form::text(‘name’, $value = null, array(‘class’ => ‘form-control’, ‘placeholder’ => ‘Your Name’)) }}
</div>
<div class=”form-group”>
@if(!empty($errors->first(‘comment’)))
<div class=”alert alert-danger”>{{ $errors->first(‘comment’) }}</div>
{{ Form::label(‘comment’, ‘Comment’) }}
{{ Form::textarea(‘comment’, $value = null, array(‘class’ => ‘form-control’, ‘rows’ => ‘4')) }}
</div>
{{ Form::submit(‘Comment Now’, array(‘class’ => ‘btn btn-default’)) }}
{{ Form::close() }}
</div>
Then, add this route to routes.php to handle the comment form post request:
Route::post(‘/comment/{id}’, ‘CommentController@comment’);
Next, add the new comment method to CommentController with this code block:
public function comment($id) {
$rules = array(
‘name’ => ‘required’,
‘comment’ => ‘required’,
);
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
return Redirect::to(‘/blog/comment/’.$id)
->withErrors($validator)
->withInput(Input::except(‘password’));
} else {
// store
$comment = new Comment; $comment->post_id = $id;
$comment->name = Input::get(‘name’);
$comment->comment = Input::get(‘comment’);
$comment->save();
// redirect
return Redirect::to(‘/blog/’.$id);
}
}
Now, you will need to add this code block to Post Model to manage the number of comments on your blog posts:
public function comments()
{
return $this->hasMany(‘Comment’);
}
Then, add this to your comment model too:
public function post()
{
return $this->belongsTo(‘Post’);
}
To show all comments, replace this code:
$blog = Post::find($id);
- With this code:
$blog = Post::with(‘comments’)->find($id);
Then, add this code block to your blog detail view:
<div class=”col-md-12">
<hr>
@foreach($blog->comments as $comment)
<span>{{{ $comment->name }}}</span>
<p class=”lead”>{{{ $comment->comment }}}</p>
<hr>
</div>
Of course, you need to commit/push everything with this command on your terminal:
git add.
git commit -m “Added Comment”
git push origin master
Finally, to add a flash message on your home view, add this code to your home view’s container:
@if (Session::has(‘message’))
<div class=”col-md-12">
<div class=”alert alert-info”>{{ Session::get(‘message’) }}</div>
</div>
Then, run this command on your terminal:
git add.
git commit -m “Added Flash Message on homepage”
git push origin master
Now, your blog is all set and ready to go. The next thing on your list would be to come up with a theme for your blog and start brainstorming ideas for your blog posts to get your blog up and running.