My First Time Using Laravel

Jul 21, 2025    m. Jul 21, 2025    #php   #laravel   #programming  

As a developer I have always been curious about different frameworks that can make building web applications easier and more enjoyable. My general test for new frameworks is how quickly a pastebin style or imgur style webiste can be built.

Recently I decided to dive into Laravel one of the most popular PHP frameworks. After watching ThePrimeagen ‘Launching a site in one day… WITH PHP?’

It was amazing to see how quickly a site can be developed using Laravel and how great there starter kits are. Laravel has great first party packages that allow you to rapidly develop a website with ease and alot is already built into the framework

Starter Kits

Livewire Starter Kit

The Livewire starter kit provides a starting point for building Laravel applications with a Laravel Livewire frontend.

Livewire is a pretty cool way to build dynamic, reactive, frontend UIs using just PHP. It’s great when you want to pull in frammeworks like Vue or React

The Livewire starter kit utilizes Livewire, Tailwind, and the Flux UI component library.

Vue Starter Kit

There is also a Vue starter although I havent used this starter kit directly

React Starter Kit

There is also a React starter although I havent used this starter kit directly

Auth

When I first started building websites with Laravel one of my biggest concerns was authentication. I wanted something secure, easy to set up, and flexible. Auth is a PITA ass at times and getting it right is hard. Thankfully Laravel ships with some auth already built in with its ‘session’ guard.

In Laravel middleware acts like a gatekeeper for routes. It can check requests before they reach controllers making sure users meet certain conditions like being logged in.

Using the auth middleware is as easy as attaching it to your route definition. Here’s how you can do it:

Route::view('dashboard', 'dashboard')
    ->middleware(['auth', 'verified', CheckIfUserDisabled::class])
    ->name(name: 'dashboard');

We also have more middlewars attached to this route being both ‘verified’ and ‘CheckIfUserDisabled’ which is my own custom middleware. And is used to verify if the account has been disabled. Its a little jank but it works. Problem is it only verifies if the user is disabled on request to authenticated pages rather then on the login request. This could most likely to rebuilt in a better way and do a check on login if the account is disabled buuuut I haven’t got aroound in doing that yet.

class CheckIfUserDisabled
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        if (Auth::check() && !Auth::user()->active) {
            Auth::logout();
            $request->session()->invalidate();
            $request->session()->regenerateToken();
            return redirect('/')->with('status', 'Your account has been disabled.');
        } else {
            return $next($request);
        }
    }
}

Custom Middleware

Adding custom middleware in Laravel is very easy thankfully, an example middleware is we can create is an isAdmin middleware. Rather then using Sanctum we can quickly create a middleware which verifies the authenticated user isAdmin()


class IsAdmin
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle($request, Closure $next)
    {
        if (!Auth::check() || !Auth::user()->isAdmin()) {
            abort(403, 'Unauthorized');
        }
        return $next($request);
    }
}

isAdmin is a function we create in the User model

public function isAdmin()
{
    return $this->is_admin;
}

Database Migrations and Seeders

As your project grows keeping your database structure organized and consistent becomes crucial. Laravel’s migrations and seeders are powerful tools that help you manage your database schema and populate it with test data—all from PHP code.

Here’s an example migration that creates three tables: users, password_reset_tokens, and sessions:


<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });

        Schema::create('password_reset_tokens', function (Blueprint $table) {
            $table->string('email')->primary();
            $table->string('token');
            $table->timestamp('created_at')->nullable();
        });

        Schema::create('sessions', function (Blueprint $table) {
            $table->string('id')->primary();
            $table->foreignId('user_id')->nullable()->index();
            $table->string('ip_address', 45)->nullable();
            $table->text('user_agent')->nullable();
            $table->longText('payload');
            $table->integer('last_activity')->index();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('users');
        Schema::dropIfExists('password_reset_tokens');
        Schema::dropIfExists('sessions');
    }
};

To run the migrations we can use:

php artisan migrate

And we can rollback with below:

php artisan migrate:rollback

SEEEDERS!

Seeders allow you fill your database with sample or default data. This is super handy for testing or when you want to quickly set up a fresh install of your app.

Here is a simple example of a seeder for the users table:

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class UserSeeder extends Seeder
{
    public function run(): void
    {
        DB::table('users')->insert([
            'name' => 'Test User',
            'email' => 'test@example.com',
            'password' => Hash::make('password'),
        ]);
    }
}

Seeders can be run with:

php artisan db:seed

Why Use Migrations?

Deployment

laravel-octane-dockerfile

This stack is built specifically to harness the performance gains of Laravel Octane. If you prefer FrankenPHP, Swoole, or RoadRunner, you can swap in your preferred Octane server and get instant speed boosts, zero boot time, and async capabilities.

Awesome Docker Compose

A stacked docker-compose.yml starts a full stack so you don’t have to piece things together yourself. Included below:

Security Hardened

Security is baked in from the start. The stack follows best practices such as:



Next: What an Old Post - Discord microservices