Implement Laravel Based Blog With HTML Website

Implement Laravel Based Blog With HTML Website

Implement Simple Laravel Blog With Authentication In Your HTML Website

·

9 min read

For self-learners and enthusiasts, it often becomes difficult to fathom where to start. Going through this vanilla implementation will give you a taste of what Laravel is. A good front-ender must know all the frameworks available to leverage for development. Start your Laravel developing experience right now!

Pre-Prerequisites

Steps in the content, assume you have the following things satisfied.

Apache Server (Expand To See More)
Or nginx, If you prefer. Setup and configure Apache - https://ubuntu.com/tutorials/install-and-configure-apache#1-overview
sudo apt-get install apache2
# Or
sudo apt-get install nginx

Going through the above guide for setting up Apache will brush up on your basics on setting up servers Or give you a clear understanding of how servers are configured to host HTML and many other web development codes.

Database
MySQL or PostgreSQL. Create new user in MySql - You can then use localhost/phpmyadmin to create the database. Use Credentials of created user. | Search Google: How To Create MySQL User
sudo apt-get install mysql-server mysql-client
# Or
sudo apt-get install postgresql postgresql-contrib
php
Latest version is 8.3.8
sudo apt-get update
sudo apt-get install php7.4 php7.4-cli php7.4-common php7.4-json php7.4-opcache php7.4-mbstring php7.4-xml php7.4-zip php7.4-bcmath php7.4-gd php7.4-mysql php7.4-pgsql php7.4-sqlite3 php7.4-curl php7.4-intl php7.4-readline
Composer
Install php first.
# This Is Global Installation
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
sudo mv composer.phar /usr/local/bin/composer

Ensure all the directory you will be using has permission 755.

You can replicate the steps for WAMP server, figure that out on your own, you'll learn a lot along the way.

Prerequisites

  • A MySQL User Account With All Privileges (See Above).

  • A Blank Database With Whichever Name You Like. (Use PHPMyAdmin).

  • A curious mind.

Step 1: Set Up Laravel Project

1.1 Create Laravel Project

composer create-project --prefer-dist laravel/laravel blogs
# OR
composer create-project --prefer-dist laravel/laravel . # For Current Dir

1.2 Navigate to Project Directory

cd blogs

1.3 Set Up Environment

cp .env.example env
## then
php artisan key:generate

1.4 Edit .env file

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=YOUR_DATABASE_NAME
DB_USERNAME=USERNAME
DB_PASSWORD=PASSWORD

1.5 Run Migrations

php artisan migrate

Step 2: Set Up Authentication

2.1 Install Laravel Breeze:

composer require laravel/breeze --dev

2.2 Install Breeze:

php artisan breeze:install

2.3 Install NPM Dependencies:

npm install && npm run dev

2.4 Create An Admin

Before continuing to next step you would want to create a Admin and Passwords in your created database to authenticate your blog login. You can do this in three easy steps -

  1. Log in to localhost/phpmyadmin with the created MySQL username and password.

  2. Locate your database for the blog.

  3. In the table, locate users and add a new field. Add username, ID, email, and password. VERY IMPORTANT: Select password_hash PHP Function from the dropdown menu in the password field.

OR

After setting up the blog you can use Breeze register form at /admin/register

Step 3: Create Blog Model, Migration, and Controller

3.1 Create Blog Model and Migration

php artisan make:model Blog -m

3.1.A Edit Blog Model To Add Fillable Content

app/models/Blog.php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Blog extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'content', 'author'];
}

3.2 Define the Blog Migration

Open the migration file in database/migrations/ and define the schema

public function up()
{
    Schema::create('blogs', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->text('content');
        $table->string('author');
        $table->timestamps();
    });
}

3.3 Run the Migration

php artisan migrate

3.4 Create Blog Controller

php artisan make:controller BlogController

Step 4: Define Routes

Open routes/web.php and add the necessary routes

use App\Http\Controllers\BlogController;

Route::middleware(['auth'])->group(function () {
    Route::get('/admin/blogs', [BlogController::class, 'index'])->name('blogs.index');
    Route::get('/admin/blogs/create', [BlogController::class, 'create'])->name('blogs.create');
    Route::post('/admin/blogs', [BlogController::class, 'store'])->name('blogs.store');
    Route::get('/admin/blogs/{blog}/edit', [BlogController::class, 'edit'])->name('blogs.edit');
    Route::put('/admin/blogs/{blog}', [BlogController::class, 'update'])->name('blogs.update');
    Route::delete('/admin/blogs/{blog}', [BlogController::class, 'destroy'])->name('blogs.destroy');
});

Route::get('/blogs', [BlogController::class, 'showAll'])->name('blogs.showAll');
Route::get('/blogs/{blog}', [BlogController::class, 'show'])->name('blogs.show');

Step 5: Implement Controller Methods

Open app/Http/Controllers/BlogController.php and implement the methods

<?php

namespace App\Http\Controllers;

use App\Models\Blog;
use Illuminate\Http\Request;

class BlogController extends Controller
{
    public function index()
    {
        $blogs = Blog::all();
        return view('admin.blogs.index', compact('blogs'));
    }

    public function create()
    {
        return view('admin.blogs.create');
    }

    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'title' => 'required',
            'content' => 'required',
            'author' => 'required',
        ]);

        Blog::create($validatedData);
        return redirect()->route('blogs.index')->with('success', 'Blog created successfully.');
    }

    public function edit(Blog $blog)
    {
        return view('admin.blogs.edit', compact('blog'));
    }

    public function update(Request $request, Blog $blog)
    {
        $request->validate([
            'title' => 'required',
            'content' => 'required',
            'author' => 'required',
        ]);

        $blog->update($request->all());
        return redirect()->route('blogs.index')->with('success', 'Blog updated successfully.');
    }

    public function destroy(Blog $blog)
    {
        $blog->delete();
        return redirect()->route('blogs.index')->with('success', 'Blog deleted successfully.');
    }

    public function showAll()
    {
        $blogs = Blog::all();
        return view('blogs.index', compact('blogs'));
    }

    public function show(Blog $blog)
    {
        return view('blogs.show', compact('blog'));
    }
}

Step 6: Create Views

6.1 Admin Blog Index

Create resources/views/admin/blogs/index.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Blogs</h1>
    <a href="{{ route('blogs.create') }}" class="btn btn-primary">Create Blog</a>
    @foreach ($blogs as $blog)
        <div>
            <h2>{{ $blog->title }}</h2>
            <p>{{ $blog->author }}</p>
            <a href="{{ route('blogs.edit', $blog->id) }}" class="btn btn-warning">Edit</a>
            <form action="{{ route('blogs.destroy', $blog->id) }}" method="POST" style="display: inline;">
                @csrf
                @method('DELETE')
                <button type="submit" class="btn btn-danger">Delete</button>
            </form>
        </div>
    @endforeach
</div>
@endsection

6.2 Admin Blog Create and Edit Forms

Create resources/views/admin/blogs/create.blade.php and edit.blade.php

create.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Create Blog</h1>
    <form action="{{ route('blogs.store') }}" method="POST">
        @csrf
        <div class="form-group">
            <label for="title">Title</label>
            <input type="text" name="title" id="title" class="form-control" required>
        </div>
        <div class="form-group">
            <label for="author">Author</label>
            <input type="text" name="author" id="author" class="form-control" required>
        </div>
        <div class="form-group">
            <label for="content">Content</label>
            <textarea name="content" id="content" class="form-control" required></textarea>
        </div>
        <button type="submit" class="btn btn-primary">Create</button>
    </form>
</div>
@endsection

edit.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Edit Blog</h1>
    <form action="{{ route('blogs.update', $blog->id) }}" method="POST">
        @csrf
        @method('PUT')
        <div class="form-group">
            <label for="title">Title</label>
            <input type="text" name="title" id="title" class="form-control" value="{{ $blog->title }}" required>
        </div>
        <div class="form-group">
            <label for="author">Author</label>
            <input type="text" name="author" id="author" class="form-control" value="{{ $blog->author }}" required>
        </div>
        <div class="form-group">
            <label for="content">Content</label>
            <textarea name="content" id="content" class="form-control" required>{{ $blog->content }}</textarea>
        </div>
        <button type="submit" class="btn btn-primary">Update</button>
    </form>
</div>
@endsection

6.3 Public Blog Views

Create resources/views/blogs/index.blade.php and show.blade.php

index.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Blogs</h1>
    @foreach ($blogs as $blog)
        <div>
            <h2><a href="{{ route('blogs.show', $blog->id) }}">{{ $blog->title }}</a></h2>
            <p>{{ $blog->author }}</p>
            <p>{{ Str::limit($blog->content, 150) }}</p>
        </div>
    @endforeach
</div>
@endsection

show.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>{{ $blog->title }}</h1>
    <p>{{ $blog->author }}</p>
    <p>{{ $blog->content }}</p>
</div>
@endsection

Step 7: Integrate Your CSS and HTML Templates

7.1 Place Your CSS and JS Files

Copy your CSS files to public/css and JS files to public/js.

7.2 Update Blade Templates

Create a master layout file resources/views/layouts/app.blade.php to include your CSS and JS files

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Your Blog</title>
    <link rel="stylesheet" href="{{ asset('css/style.css') }}">
</head>
<body>
    <div class="container">
        @yield('content')
    </div>
    <script src="{{ asset('js/script.js') }}"></script>
</body>
</html>

7.3 Update Other Blade Templates to Extend Layout

For example, resources/views/admin/blogs/show.blade.php

@extends('layouts.app') <!-- Like This -->

@section('content')
<div class="container">
    <h1>{{ $blog->title }}</h1>
    <p>{{ $blog->author }}</p>
    <p>{{ $blog->content }}</p>
</div>
@endsection

7.4 Integrate Custom HTML Templates

  • If you have custom HTML templates, you can include them in your Blade views.

  • For example, to include a header and footer, create resources/views/partials/header.blade.php and footer.blade.php

header.blade.php

<header>
    <nav>
        <!-- Your navigation items -->
    </nav>
</header>

footer.blade.php

<footer>
    <!-- Your footer content -->
</footer>

Include these partials in your layout file app.blade.php

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Your Blog</title>
    <link rel="stylesheet" href="{{ asset('css/style.css') }}">
</head>
<body>
    @include('partials.header')
    <div class="container">
        @yield('content')
    </div>
    @include('partials.footer')
    <script src="{{ asset('js/script.js') }}"></script>
</body>
</html>

Step 9: Install a Rich Text Editor (Optional)

To provide a better content editing experience for the admin, you can install a rich text editor like CKEditor.

9.1 Install CKEditor

npm install ckeditor4

9.2 Include CKEditor in Your Create and Edit Forms

Update create.blade.php and edit.blade.php to include CKEditor

create.blade.php

<!-- Remaining Code -->

<script src="{{ asset('ckeditor/ckeditor.js') }}"></script>
<script>
    CKEDITOR.replace('content');
</script>
@endsection

edit.blade.php

<!-- Remaining Code -->

<script src="{{ asset('ckeditor/ckeditor.js') }}"></script>
<script>
    CKEDITOR.replace('content');
</script>
@endsection

Step 10: Test Your Application

Visit the following routes in your browser to test your application:

Admin Dashboard

http://localhost:8000/admin/blogs for viewing all blogs.

http://localhost:8000/admin/blogs/create for creating a new blog.

Public Blog Pages

http://localhost:8000/blogs for viewing all blogs.

http://localhost:8000/blogs/{blog} for viewing a specific blog.

Step 11: Add Slug In URL (Optional)

11.1 Add a Slug Field to the Blogs Table

First, you need to add a slug column to your blogs table. Create a new migration for this

php artisan make:migration add_slug_to_blogs_table --table=blogs

In the generated migration file, add the slug column

public function up()
{
    Schema::table('blogs', function (Blueprint $table) {
        $table->string('slug')->unique()->after('title');
    });
}

public function down()
{
    Schema::table('blogs', function (Blueprint $table) {
        $table->dropColumn('slug');
    });
}

Run the migration

php artisan migrate

11.2 Generate Slugs Automatically

Update your Blog model to automatically generate slugs from titles when creating or updating a blog post.

app/Models/Blog.php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class Blog extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'content', 'author', 'slug'];

    public static function boot()
    {
        parent::boot();

        static::creating(function ($blog) {
            $blog->slug = Str::slug($blog->title);
        });

        static::updating(function ($blog) {
            $blog->slug = Str::slug($blog->title);
        });
    }
}

11.3 Update Routes and Methods to Use Slugs

Update your routes to use the slug instead of the id

routes/web.php

use App\Http\Controllers\BlogController;

Route::middleware(['auth'])->group(function () {
    Route::get('/admin/blogs', [BlogController::class, 'index'])->name('blogs.index');
    Route::get('/admin/blogs/create', [BlogController::class, 'create'])->name('blogs.create');
    Route::post('/admin/blogs', [BlogController::class, 'store'])->name('blogs.store');
    Route::get('/admin/blogs/{blog}/edit', [BlogController::class, 'edit'])->name('blogs.edit');
    Route::put('/admin/blogs/{blog}', [BlogController::class, 'update'])->name('blogs.update');
    Route::delete('/admin/blogs/{blog}', [BlogController::class, 'destroy'])->name('blogs.destroy');
});

Route::get('/blogs', [BlogController::class, 'showAll'])->name('blogs.showAll');
Route::get('/blogs/{slug}', [BlogController::class, 'show'])->name('blogs.show');

Update your BlogController to find blogs by slug instead of id.

app/Http/Controllers/BlogController.php

namespace App\Http\Controllers;

use App\Models\Blog;
use Illuminate\Http\Request;

class BlogController extends Controller
{
    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'title' => 'required',
            'content' => 'required',
            'author' => 'required',
        ]);

        $blog = Blog::create($validatedData);

        return redirect()->route('blogs.show', $blog->slug)->with('success', 'Blog created successfully.');
    }

    public function show($slug)
    {
        $blog = Blog::where('slug', $slug)->firstOrFail();
        return view('blogs.show', compact('blog'));
    }
}

11.4 Handle Slug Uniqueness

Ensure slugs are unique by appending a counter if a slug already exists. You can update the model's slug generation logic

app/Models/Blog.php

class Blog extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'content', 'author', 'slug'];

    public static function boot()
    {
        parent::boot();

        static::creating(function ($blog) {
            $blog->slug = static::createSlug($blog->title);
        });

        static::updating(function ($blog) {
            $blog->slug = static::createSlug($blog->title, $blog->id);
        });
    }

    public static function createSlug($title, $id = 0)
    {
        $slug = Str::slug($title);
        $originalSlug = $slug;
        $count = 1;

        while (static::where('slug', $slug)->where('id', '!=', $id)->exists()) {
            $slug = "{$originalSlug}-{$count}";
            $count++;
        }

        return $slug;
    }
}

Summing Up :)

The main usage of Laravel is for developing the back-end functionalities of high-performing web applications, including content management systems (like the blog you created above), websites, and APIs. Laravel is known for its elegant syntax and powerful features, making it a framework for Web Artisans. While Laravel provides robust tools and an efficient syntax for back-end development, it is often used in conjunction with front-end technologies like HTML, CSS, and JavaScript to create complete web applications. Think of Laravel as the foundation and logic of your application. HTML, CSS, and JavaScript are the tools used to build and style the user interface. It's a canvas; you are the painter, and HTML, CSS, and JavaScript are your paints and brushes. Consider to outsource Laravel Development services to a bespoke company to satisfy your Laravel needs affordably and expeditiously.

About Me

I'm An employee at a reputed outsource web development company; I mainly work on optimizing web apps, websites, and mobile apps {created on different frameworks and technologies} for speed, search engine optimization, and user accessibility.

Laravel Logo Minimum