Simple Blog in Laravel

The purpose of this story is to get started with Laravel and create a very simple project. Uses Laravel 8.

Prerequisites

In order to install and run the Laravel project we need to have:

  1. Composer, a PHP dependency manager (for Windows download the exe installer)
  2. npm, a JavaScript packeage manager. Install Node.js in order to have npm, too.
  3. A command line terminal. If you are on windows I recommend GitBash which is installed along with Git.

Create a new Laravel project

There are many different ways to create a new project, here we use composer:

composer create-project laravel/laravel blog

This will download all necessary dependencies and will create the new project in a folder named blog.

Change directory into the newly created blog folder.

Examining files and folders

Opening the project folder with an IDE like Visual Studio Code or PhpStrom we see a long list of files and folders. In order to build this project we are going to use the following:

  1. .env: configuration file
  2. artisan: command line tool used to perform many tasks in Laravel
  3. app/Models: folder to hold models
  4. app/Http/Controllers: folder where controllers are located
  5. database/migrations: migration files, used to maintain tables in the database
  6. resources/views: here we add the user interface pages as blade templates
  7. routes/web.php: in this file the urls of the app are defined as routes and they are associated to a controller and a function in the controller

Run the application by:

php artisan serve

then open http://127.0.0.1:8000 and you will see the default Laravel home page.

Database

Create a database using any tool you prefer. Here we created a MySQL database using phpMyAdmin called blog and a user bloguser which is granted all privileges to this database.
Then provide this information in the .env file (change according to whatever was used as DB name, user, and password):

DB_DATABASE=blog
DB_USERNAME=bloguser
DB_PASSWORD=1111

Migrations is a powerful mechanism to maintain the database schema through the application. This is very convenient because everything related to the database structure is in migration files. These files are committed to Git and shared on GitHub, hence, everyone on the team will get the latest migration files and can run a migration in order to have the database schema in the same state as everyone else in the team.

In the migrations folder there are already three (3) migrations and they are applied by running:

php artisan migrate

Checking the database we see four tables: users, password_resets, failed_jobs, and migrations. The last one keeps track of the migrations applied.

Authentication

Laravel has scaffolded authentication kits. The easiest for beginners is Breeze. Install it by:

composer require laravel/breeze --dev
php artisan breeze:install
npm install
npm run dev

Now the home page has links for Login and Registration and we can create (register) some users.

Blog Posts

In order to add blog posts we need to create the respective table in the database. Laravel has an Object to Relational Mapping (ORM) mechanism called Eloquent . ORM associated model classes to the respective database tables using dome conventions. The class name of the model will be associated to the same name table in the database but in plural. For example the class Blogpost interacts with the blogposts table.

First create a migration:

php artisan make:migration create_blogpost_table --creat=blogposts

and a model:

php artisan make:model Blogpost

In the migration file that is created we add the columns necessary for the blog post: title, content, and the user_id which defines the user who wrote this post.
Also, the user has a one-to-many relationship with the blogpost and this relationship will be defined in the migration.

public function up()
{
     Schema::create('blogposts', function (Blueprint $table) {
         $table->id();
         $table->string('title');
         $table->text('content');
         $table->unsignedBigInteger('user_id');
         $table->timestamps();

         $table->foreign('user_id')->references('id')->on('users');
     });
}

Finally, in order to be able to use the relationship we add the following function to the User model:

public function blogposts() {
        return $this->hasMany(Blogpost::class);
}

Adding routes and controller

We will add the following pages:

  1. /users: Displays a list of the users. Each user is a link that leads to the blog of the respective user.
  2. /user/id: Displays the blog of a specific user. The id of the user is provided as part of the URL.
  3. /addblogpost: Adds a new post
Route::get('/users', [BlogController::class, 'users']);
Route::get('/user/{id}', [BlogController::class, 'user']);
Route::post('/addblogpost', [BlogController::class, 'addblogpost'])->middleware(['auth']);

Each route is associated with a function in the BlogController. Controllers organise the behaviour of each route as functions in a controller class.

The BlogController is created by:

php artisan make:controller BlogController

and contains the respective functions for each route:

Function users retrieves all users from the database and invokes the users view

public function users() {
     $context['users'] = User::all();

     return view('users', $context);
}

Function user retrieves the user defined in the URL by its id and invokes the user view

public function user($id) {
     $context['user'] = User::find($id);

     return view('user', $context);
}

Function addblogpost retrieves the data submitted by the user via a form

public function addblogpost(Request $request) {
        $user = auth()->user();
        $blogpost = new Blogpost();
        $blogpost->title = $request->get('title');
        $blogpost->content = $request->get('content');
        $blogpost->user_id = $user->id;
        $blogpost->save();

        return redirect('dashboard');
 }

The context associative array in these functions plays the role of a bag where we can put any data that should be submitted to the view in order to be displayed. Whatever subscript we use for this array will be found as a variable in the view.

Views

Views are using the blade templating system . This has the benefit of adding minimal code in the web page which makes maintenance and design much easier.

View users receives a list of User objects from the controller and displays them in a loop:

<h1>Users</h1>
@foreach($users as $user)
    <p><a href="/user/{{ $user->id }}">{{ $user->name }}</a></p>
@endforeach

View user receives the data of the user specified by its id in the URL and displays the user name and the user's blog posts. Blog posts are accessed using the relationship function we added in the User model.

<h1>{{ $user->name }}</h1>
@foreach($user->blogposts as $blogpost)
     <div>
         <h2>{{ $blogpost->title }}</h2>
         <p>{{ $blogpost->content }}</p>
     </div>
@endforeach

In the existing dashboard View, a form is added. This form contains a @csrf statement which adds a hidden field with a random value in order to protect from Cross-Site Request Forgery attacks.

<h2>Add blogpost</h2>
<form method="post" action="/addblogpost">
        @csrf
        Title: <input type="text" name="title" /><br>
        Content: <textarea name="content"></textarea><br>
        <input type="submit">
 </form>

Endnote

This is a very simple (and not so interesting) Laravel application, aiming to introduce the key components of the framework.
It can be used as a basis for further development, for example to create a clone of a blog application like Wordpress.