Back to BlogOct 2025

Getting started with Laravel 12

Getting started with Laravel 12

🚀 Getting Started with Laravel 12 — A Hands-On Beginner’s Guide

Laravel is one of the most popular PHP frameworks for building modern web applications. It’s elegant, expressive, and designed to make development enjoyable.

In this post, we’ll go step-by-step through the basics of Laravel 12, including setup, routes, views, Blade templates, and models — everything you need to get a simple app up and running.


Introduction / Motivation

I still remember when I first started learning Laravel many years ago — it felt exciting but also a bit overwhelming. Laravel is a full-featured framework, and at first glance, there’s a lot to take in.

With this guide, my goal is to introduce you to Laravel in the simplest way possible — focusing only on the essentials you need to understand how it works. From there, you’ll have a solid foundation to keep building at your own pace.

If I don’t go too deep into certain topics, it’s intentional — I want to keep things clear, avoid confusion, and prevent overheating your brain’s processor chip 🧠💥.


💡 Inspiration & Acknowledgement

Much of this guide was inspired by the YouTube tutorial “Laravel From Scratch” by Traversy Media — one of my favorite teachers on the internet.

That tutorial was released a few years ago, so in this updated version, I’ve added notes and adjustments to reflect what’s changed in Laravel 12.

Full tutorial by Traversy Media:

Traversy Media Laravel Tutorial Link

Let’s get started. 🚀


🚀 1. Setting Up Laravel Valet (Mac)

Laravel Valet is a lightweight development environment for macOS that lets you run Laravel (and other PHP) sites locally — instantly, without messing around with virtual hosts or Docker setups.
It’s simple, fast, and perfect for developers who prefer a minimal setup.

I recommend following Brad Traversy’s setup guide here:
👉 Brad’s Laravel Valet Gist

For Windows users, you can use XAMPP (I recommend following Brad’s advice in his video).


⚠️ Stop Apache (if needed)

On macOS, Apache often runs automatically on port 80, which is the same port Laravel Valet uses.
To avoid conflicts, stop Apache before using Valet:

sudo apachectl stop

or

brew services stop httpd

You can verify port 80 is now free with:

sudo lsof -i :80

If nothing shows up, the port is clear. Once Valet is installed, confirm it’s working by checking the version:

valet --version

You can also see all available Valet commands by running:

valet list

⚡️ Create a New Laravel Project

Navigate to the folder where you want to store your projects, then run: For the sake of having an easy guide and be used as complemetary or Brad's video I will use same naming:

laravel new laragigs

This will create a new Laravel project called laragigs. Next, “park” the directory with Valet:

valet park
What Does valet park Do? When you run valet park, Valet “links” the current folder as a location to serve all projects inside it automatically. This means each project folder becomes accessible at projectname.test without additional configuration.

Example:

/Users/you/Sites/laragigs → http://laragigs.test

/Users/you/Sites/blog → http://blog.test

__

Now open the project in VS Code:

code .

Visit your new site in the browser: 👉 http://laragigs.test

You should see the Laravel welcome page.

Explore the Key Directories

At this stage, let’s look at a few important folders in your new project (and ignore the rest for now):

routes/
 └── web.php              ← Main web routes
resources/views/
 └── welcome.blade.php    ← Your first Blade template
app/Models/               ← Where Eloquent models live

What are Routes?

Routes are like a map for your web application. They define how your application should respond when a user visits a specific URL: ‘/about’, ‘/’, /listings/{id}’

What are Views and what is Blade?

The View is data that is going to be displayed to the user on their browser and the user can interact with it.

Blade is Laravel’s built-in templating engine. It lets you write clean, reusable HTML with simple, elegant syntax — like embedding PHP logic directly into your templates using null and control structures such as @if, @foreach, and more.

<h1>{{ $title }}</h1>
@foreach ($listings as $listing)
 <p>{{ $listing->title }}</p>
@endforeach

Blade templates are stored inside the resources/views folder and always end with the .blade.php extension. If you wish you can also use plain php alternatively. You can learn more here: https://laravel-docs.readthedocs.io/en/latest/blade/

What are Models?

A Model in Laravel is a PHP class that symbolizes a database table. It is in charge of maintaining the data in the table and giving users a way to interact with it.

Routes (hands on)

Go to routes/web.php

TIP: a shortcut in VSCODE is command + P and search for the name of the file

Let’s say you want to create a new page/url for the About page:

## web.php
Route::get('/about', function () {
   return response('<h1>About</h1>', 200)
       ->header('Content-Type', 'text/plain');
});

Then you can go and refresh your browser: http://laragigs.test/about

And you will see the new route created. Notice in this example that we are directly passing the information/data to be rendered (the html h1). As opposed to passing a “view” from ‘resources/views’.

Check this 2 more examples, copy and paste and try to understand what is going on:

Route::get('/posts/{id}', function ($id) {
   return response('Post '. $id);
})->where('id', '[0-9]+');

Above, we are creating a dynamic route and passing an id, also setting the id must be a number

Second example:

Route::get('/search', function(Request $request) {
//    dd($request->name . ' ' . $request->city);
  return $request->name . ' ' . $request->city;
});

In this example we are creating a search page and returning the query parameters http://laragigs.test/search?city=Brisbane&name=Nic In your browser you should see Name from city

Notice also dd(). is a helper function that stands for "Dump and Die." It is a crucial tool for debugging.

API ROUTES

You can skip this part if you feel it as it will not affect the rest.

In the youtube tutorial Brad does a demostration creating a route for API. Laravel 12 does not include by default routes/api.php

If your application will also offer a stateless API, you may enable API routing using the install:api Artisan command (laravel documentation) :

php artisan install:api

The install:api command installs Laravel Sanctum, which provides a robust, yet simple API token authentication guard which can be used to authenticate third-party API consumers, SPAs, or mobile applications. In addition, the install:api command creates the routes/api.php

Views (hands on)

  1. Go to resources/views/welcome.blade.php
  2. Rename the file to: resouces/views/listings.blade.php
  3. Delete all content inside and just place <h1>Listings Page</h1> on it
  4. Go back to routes/web.php
  5. Add the following code:
Route::get('/', function () {
  return view('listings');
});

As you can see, now we are returning the view of Listings which matches with the name you have in resources/views/listings.blade.php. If you go to / you should see the content of that file.

Now let's pass some static data:

Route::get('/', function () {
  return view('listings', [
   'heading' => 'Latest Listings',
   'listings' => [
       [
           'id' => 1,
           'title' => 'Listing One',
           'description' => 'This is the first listing'
       ],
       [
           'id' => 2,
           'title' => 'Listing Two',
           'description' => 'This is the second listing'
       ],
       [
           'id' => 3,
           'title' => 'Listing Three',
           'description' => 'This is the third listing'
       ],
   ]
  ]);
});
  • Go to resources/views/listings.blade.php and paste the following code:
<h1>{{ $heading }}</h1>
@foreach ($listings as $listing)
  <h2>
    {{ $listing['title'] }}
  </h2>~
  <p>
    {{ $listing['description'] }}
  </p>
@endforeach
  • Before refreshing the browser, take some time to inspect the code above and try to understand what is going on and what you probably will see in the browser. Mental visualize how the routes and views and connected.
  • Note: Inside of the view you have access to the data you as passing on the route. $heading & listings
  • Note: @foreach which are blade templating language, very similar to php but cleaner.

Models (Hands-On)

  1. Go To app/Models and create a new file called Listing.php. Later on, this will come from the database.
<?php
 namespace App\Models;


 Class Listing {


   public static function all() {
     return [
       [
         'id' => 1,
         'title' => 'Listing One',
         'description' => 'This is the first listing'
       ],
       [
         'id' => 2,
         'title' => 'Listing Two',
         'description' => 'This is the second listing'
       ],
       [
         'id' => 3,
         'title' => 'Listing Three',
         'description' => 'This is the third listing'
       ],
     ];
   }


   public static function find($id) {
     $listings = self::all();
    
     foreach($listings as $listing) {
       if($listing['id'] == $id) {
         return $listing;
       }
     }


   }
 }
  • If you are completely new in Laravel and/or PHP, pay special attention to:
    • Namesepace (below more information)
    • Naming (follow naming coventions)
    • the self. (special attribute to access functions/data inside of a php Class)
What Is a Namespace in PHP? A namespace in PHP is like a folder system for your code — it helps organize classes and prevent name conflicts. In plain terms: A namespace tells PHP where a class lives and allows you to use classes with the same name in different parts of your app.

💡 Example Let’s say you have two classes called User:

// File: app/Models/User.php
namespace App\Models;

class User {
    // Eloquent model logic
}

// File: app/Http/Controllers/User.php
namespace App\Http\Controllers;

class User {
    // Controller logic
}

Without namespaces, PHP would get confused — because it wouldn’t know which User you meant. But with namespaces, each one has its own address:

App\Models\User

App\Http\Controllers\User

So they can coexist perfectly fine. Laravel organizes almost everything using namespaces.

--

Lets update resources/views/listings.blade.php
<h1>{{ $heading }}</h1>
@unless(count($listings) == 0)
 <p>No listings found.</p>
@foreach ($listings as $listing)
 <h2>
   <a href="/listings/{{ $listing['id'] }}">
     {{ $listing['title'] }}
   </a>
 </h2>~
 <p>{{ $listing['description'] }}</p>
@endforeach


@else
 <p>No listings found.</p>
@endunless
Lets update resources/routes/web.php
  • First, we need to import the Listing model at the top of the file.
  • Then, in our route, we return the listing view and pass it a single Listing object by calling the find method, which receives the id from the URL.
## Single Listing
use App\Models\Listing;

Route::get('/listings/{id}', function($id) {
   return view('listing', [
       'listing' => Listing::find($id)
   ]);
});
Lastly create a new file for the single listing: resouces/views/listing.blade.php
<h1>{{ $listing['title'] }}</h1>
<h1>{{ $listing['description'] }}</h1>

You should then be able to see all listings in the homepage, and once clicked in each listing, navigate to the individual listing page.

Summary

So Far we covered some basics including:

  • Basic routing
  • Creating Views
  • Using Blade for SSR
  • Creating a model with a class for Listing

Continuation

So far, this has been a very basic introduction or refresher to Laravel. For a deeper dive, I highly recommend following Brad’s tutorial — he explains the key concepts very clearly with practical examples.

Below, I’ve included a cheat sheet of some of Laravel’s key concepts:

__

Laravel Core Concepts — Simple Cheatsheet

  • Routes → Define the URL paths and tell Laravel which controller or action to run.
  • Views → The HTML/Blade templates shown to users.
  • Models → Represent database tables and handle data logic.
  • Controllers → Coordinate requests between routes, models, and views.
  • Migrations → Blueprints for your database structure (tables, columns).
  • Factories → Generate fake data for testing or seeding.
  • Seeders → Insert sample data into the database (can use factories).
  • Middleware → Check or modify requests before reaching controllers (e.g. auth).
  • AppServiceProvider → Register global app logic, bindings, or listeners.
  • Request / Response → The input/output objects every route works with.
  • Eloquent ORM → Laravel’s object-based way to talk to the database (via models).
  • Blade → Laravel’s templating engine for clean and reusable HTML views.
  • Service Container → Laravel’s dependency injection system (how classes get what they need).
  • Service Providers → Register or boot features into the Laravel app (AppServiceProvider is one).
  • Queues / Jobs → Run tasks in the background, like sending emails.
  • Events / Listeners → React to app actions, e.g., “UserRegistered → SendWelcomeEmail.”
  • Artisan → The command-line tool for Laravel (e.g. php artisan migrate).

Artisan common commands

## General
php artisan list             # Show all available Artisan commands
php artisan help <command>   # Show help for a specific command
php artisan serve            # Run local dev server at http://127.0.0.1:8000
php artisan tinker           # Interactive shell to test code and Eloquent
php artisan clear            # Clear cache, routes, config, and views
## Database
php artisan migrate                # Run all pending migrations
php artisan migrate:rollback       # Undo the last migration batch
php artisan migrate:fresh          # Drop all tables and re-run all migrations
php artisan db:seed                # Run all database seeders
php artisan migrate --seed         # Run migrations and seed together
php artisan make:migration create_users_table   # Create new migration file
## Make / Generate Files
php artisan make:model User                    # Create a new model
php artisan make:controller UserController      # Create a new controller
php artisan make:migration create_posts_table   # Create a new migration
php artisan make:seeder UsersTableSeeder        # Create a new seeder
php artisan make:factory UserFactory            # Create a model factory
php artisan make:middleware AuthMiddleware      # Create new middleware
php artisan make:request StoreUserRequest       # Create a form request validator
php artisan make:command MyCommand              # Create a custom Artisan command
php artisan make:observer UserObserver          # Create a model observer
## Cache / Config
php artisan cache:clear      # Clear application cache
php artisan config:clear     # Clear configuration cache
php artisan route:clear      # Clear route cache
php artisan view:clear       # Clear compiled Blade views
php artisan optimize         # Optimize performance and cache routes/config/views
## Debugging / Info
php artisan route:list        # Show all defined routes
php artisan migrate:status    # Show which migrations have run
php artisan config:cache      # Cache config for faster load times
php artisan schedule:list     # Show scheduled tasks

Conclusion

That’s all for now — may the code be with you!