Laravel Getting Started

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

This page is written against Laravel 13.x (13.34.0), checked on 2026-10-05, with the Laravel installer 5.32 and PHP 8.3 to 8.5. Every command and output was captured from a fresh application created with laravel new. Laravel 12 applications look almost the same; the differences are noted. The language itself is covered in the PHP Reference, and how PHP serves requests in The PHP Request Model and Servers.

Installing PHP, Composer and the Laravel installer

Laravel needs PHP (8.3 or newer for Laravel 13), Composer, and, for front-end assets, Node.js with npm (or Bun). The laravel command-line installer creates new applications. Three ways to get all of it:

  • php.new: one command that installs PHP, Composer and the Laravel installer on macOS, Windows or Linux, without a package manager. Re-running it updates them.

  • Laravel Herd: a native development environment for macOS and Windows with PHP, Nginx, Composer, Node and the laravel command included; applications in its "parked" directory are served automatically as https://name.test. Herd Pro adds local databases, mail and log viewers.

  • Your own PHP and Composer: install the installer with Composer.

# Linux (macOS: .../install/mac/8.5; Windows: a PowerShell one-liner on the installation page)
/bin/bash -c "$(curl -fsSL https://php.new/install/linux/8.5)"

# or, with PHP and Composer already installed
composer global require laravel/installer
laravel --version          # Laravel Installer 5.32.0

Docker users can use Laravel Sail instead of a local PHP; see Docker and Sail.

Creating an application

laravel new asks interactively for a starter kit (none, React, Svelte, Vue or Livewire), the authentication provider (Laravel’s own or WorkOS), the test framework (Pest or PHPUnit), the database, whether to install Laravel Boost, and whether to run npm install. Every question has a flag, so the command can run unattended:

$ laravel new --help
  --database=DATABASE          The database driver your application will use. Possible values are: mysql, mariadb, pgsql, sqlite, sqlsrv
  --react | --svelte | --vue | --livewire     Install a starter kit
  --livewire-class-components  Generate stand-alone Livewire class components
  --workos                     Use WorkOS for authentication
  --teams                      Install team support
  --no-authentication          Do not generate authentication scaffolding
  --pest | --phpunit           Install the Pest or PHPUnit testing framework
  --npm | --pnpm | --bun | --yarn | --no-node   Install and build front-end dependencies (or not)
  --boost | --no-boost         Install Laravel Boost to improve AI assisted coding
  --git, --github[=…]          Initialize a Git repository (and create it on GitHub)
  ...

$ laravel new bookshelf --pest --database=sqlite --no-node --no-boost --no-interaction
{"success":true,"name":"bookshelf","directory":"/home/ada/code/bookshelf"}

In non-interactive mode the installer prints only a JSON summary; interactively it shows each step. The starter kits (authentication, a dashboard, and a React, Svelte, Vue or Livewire front end) are covered on Inertia and Starter Kits and Livewire; the rest of this page uses the plain application.

What you get

The installer runs composer create-project laravel/laravel, which copies .env.example to .env, generates the APP_KEY, creates database/database.sqlite and runs the migrations. The relevant settings of the new .env:

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:...                # generated by php artisan key:generate: never commit it
APP_DEBUG=true
APP_URL=http://localhost:8000
DB_CONNECTION=sqlite              # database/database.sqlite, already migrated
SESSION_DRIVER=database
QUEUE_CONNECTION=database
CACHE_STORE=database
MAIL_MAILER=log                   # mail is written to the log in development

SQLite as the default means a new application works with no database server; sessions, the cache and the queue use database tables, so the only moving part is PHP. Switching to MySQL or PostgreSQL is a change of the DB_* variables and php artisan migrate. The .env file holds secrets and differs per machine; it is in .gitignore, and only .env.example is committed.

composer.json requires php: ^8.3, laravel/framework: ^13.17 and laravel/tinker, and for development Pest 4, Pint (the code formatter), Pail (log tailing), Collision (error output), Mockery and Faker. The skeleton installs Pest 4, not Pest 5, because Pest 5 requires PHP 8.4 and Laravel 13 still supports 8.3. A new application also contains AGENTS.md and CLAUDE.md with Laravel’s guidelines for AI coding agents.

php artisan about summarises the result:

 Environment ..
 Application Name .. Laravel
 Laravel Version .. 13.34.0
 PHP Version .. 8.3.6
 Composer Version .. 2.8.12
 Environment .. local
 Debug Mode .. ENABLED
 URL .. localhost:8000
 Maintenance Mode .. OFF

The directories and the boot file are explained on Directory Structure and Configuration.

Running it in development

cd bookshelf
npm install && npm run build      # once, to build the front-end assets
composer run dev                  # runs: php artisan dev

composer run dev runs php artisan dev (Laravel 13), which starts every process local development needs in one terminal: the PHP development server (artisan serve, on http://localhost:8000), a queue worker (queue:listen --tries=1 --timeout=0), log tailing with Pail (when the pcntl extension is available) and the Vite development server. Extra processes are registered in a service provider:

<?php
// app/Providers/AppServiceProvider.php, in boot()
use Illuminate\Foundation\DevCommands;

DevCommands::artisan('horizon', 'horizon');                 // php artisan horizon instead of queue:listen
DevCommands::node('storybook', 'storybook');                // npm run storybook
DevCommands::register('my-command --flag', 'my-process')->green();

In Laravel 12, composer run dev ran the same four processes through the concurrently npm package. Herd users skip artisan serve: Herd serves the application as https://bookshelf.test.

The first loop: route, controller, model, view

Most features follow the same path: a route maps a URL to a controller, the controller uses a model to read or write the database, and returns a view. Artisan generates the files:

$ php artisan make:model Book --migration --factory --controller --resource
 INFO Model [app/Models/Book.php] created successfully.
 INFO Factory [database/factories/BookFactory.php] created successfully.
 INFO Migration [database/migrations/2026_10_05_193247_create_books_table.php] created successfully.
 INFO Controller [app/Http/Controllers/BookController.php] created successfully.

Add the columns to the migration and run it:

<?php
// database/migrations/2026_10_05_193247_create_books_table.php (the up() method)
Schema::create('books', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->unsignedSmallInteger('published_year')->nullable();
    $table->timestamps();
});
$ php artisan migrate
 INFO Running migrations.
 2026_10_05_193247_create_books_table .. 3.11ms DONE

Declare which attributes may be mass-assigned, register the routes, and fill in two controller methods:

<?php
// app/Models/Book.php
namespace App\Models;

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

#[Fillable(['title', 'published_year'])]
class Book extends Model
{
    /** @use HasFactory<\Database\Factories\BookFactory> */
    use HasFactory;
}
<?php
// routes/web.php
use App\Http\Controllers\BookController;
use Illuminate\Support\Facades\Route;

Route::resource('books', BookController::class)->only(['index', 'show']);
<?php
// app/Http/Controllers/BookController.php
namespace App\Http\Controllers;

use App\Models\Book;
use Illuminate\View\View;

class BookController extends Controller
{
    public function index(): View
    {
        return view('books.index', ['books' => Book::orderBy('title')->get()]);
    }

    public function show(Book $book): View         // route model binding: 404 when the id does not exist
    {
        return view('books.show', ['book' => $book]);
    }
}
{{-- resources/views/books/index.blade.php --}}
<h1>Books</h1>
<ul>
    @forelse ($books as $book)
        <li><a href="{{ route('books.show', $book) }}">{{ $book->title }}</a></li>
    @empty
        <li>No books yet.</li>
    @endforelse
</ul>
{{-- resources/views/books/show.blade.php --}}
<h1>{{ $book->title }}</h1>
<p>Published {{ $book->published_year }}</p>

Add a book from the command line with Tinker, then request the pages:

$ php artisan tinker --execute="App\Models\Book::create(['title' => 'Kindred', 'published_year' => 1979]);"
$ php artisan route:list --path=books
 GET|HEAD books .. books.index › BookController@index
 GET|HEAD books/{book} .. books.show › BookController@show
 Showing [2] routes
$ curl localhost:8000/books
<h1>Books</h1>
<ul>
            <li><a href="http://localhost:8000/books/1">Kindred</a></li>
    </ul>
$ curl localhost:8000/books/1
<h1>Kindred</h1>
<p>Published 1979</p>
$ curl -o /dev/null -w '%{http_code}\n' localhost:8000/books/99
404

Everything the framework-free pages built by hand is here by convention: a front controller and router, route parameters bound to database rows (with a 404 for unknown IDs), automatic escaping in {{ }}, named routes that generate URLs, and a migration that describes the schema in code. The pages that follow take each layer in turn, starting with Request Lifecycle.

Learning resources

  • The official documentation, versioned per release; this section links the 13.x pages throughout.

  • Laravel Learn (laravel.com/learn), the official step-by-step tutorials, and Laracasts' video courses.

  • Laravel Boost, an MCP server and set of guidelines that give AI coding agents version-specific Laravel documentation and tools (composer require laravel/boost --dev, then php artisan boost:install); see AI SDK, MCP and Boost.

  • Laravel LSP (composer global require laravel/lsp), a language server for editors, used by the official VS Code, Sublime Text and Zed extensions; PhpStorm has built-in Laravel support.

Releases and support

Laravel ships one major release a year, in the first quarter. Each major release gets 18 months of bug fixes and 2 years of security fixes. Minor and patch releases come weekly and do not break compatibility. The supported versions on 2026-10-05:

Version PHP Released Bug fixes until Security fixes until

10

8.1 to 8.3

2023-02-14

2024-08-06

2025-02-04 (end of life)

11

8.2 to 8.4

2024-03-12

2025-09-03

2026-03-12 (end of life)

12

8.2 to 8.5

2025-02-24

2026-08-13

2027-02-24 (security fixes only)

13

8.3 to 8.5

2026-03-17

Q3 2027

2028-03-17

Laravel 14 is expected in the first quarter of 2027 and to require PHP 8.4. Laravel’s first-party libraries (Sanctum, Horizon and the others) support only their latest major version. Upgrading between majors is described on What’s Changed and Upgrading.

Where older books and tutorials are outdated

  • Homestead and Valet (the development environments in Laravel 5.8-era material such as Stauffer ch. 2) are legacy; use Herd, Sail or a local PHP with php artisan dev.

  • composer create-project laravel/laravel followed by php artisan key:generate and a manually created MySQL database is now one laravel new, with SQLite already migrated.

  • php artisan make:auth (Laravel 5.x) is gone; authentication comes from the starter kits (see Authentication).

  • Laravel Mix and npm run watch became Vite and npm run dev (Laravel 9.x); php artisan dev runs Vite together with the server and a queue worker.

  • The release cadence: Laravel 5.x and 6.x had six-month releases and LTS versions; since Laravel 9 there is one major release a year and no LTS.