
Chapter 20: A Gentle Introduction to Laravel
Overview
Congratulations on building a complete application from scratch! In doing so, you have manually implemented simplified versions of the key components that make up a professional web framework: routing, controllers, models, views, and a database connection. This was a fantastic learning experience, but as you can imagine, building all of that plumbing for every single project would be a lot of work.
This is why we use frameworks. A framework is a collection of pre-built, reusable components and a guiding structure that handles all the common, repetitive tasks for you. This lets you focus on what makes your application unique: its business logic.
In this chapter, we'll take a brief look at Laravel, the most popular PHP framework in the world. You'll see how the concepts you've learned map directly to Laravel's features, and you'll appreciate how much faster development can be when you stand on the shoulders of giants.
Prerequisites
Before starting this chapter, ensure you have:
- PHP 8.4 installed and available in your terminal
- Composer 2.x installed (getcomposer.org)
- Completed Chapter 19 (Building a Simple Blog) or understand MVC concepts
- A terminal/command line and text editor
- Estimated time: 35–40 minutes (20 minutes for hands-on, 15-20 minutes for reading comparisons)
Verify your setup:
# Check PHP version (should be 8.4.x)
php --version
# Check Composer version (should be 2.x)
composer --versionWhat You'll Build
By the end of this chapter, you will have:
- A new Laravel 11 project installed and running
- A database-backed "Posts" feature with:
- A
postsdatabase table created via migrations - An Eloquent
Postmodel - A
PostControllerwith an index method - A route mapped to
/posts - A Blade view displaying all posts
- A
- Sample post data to verify everything works
- Understanding of how Laravel maps to the MVC concepts you've learned
Objectives
- Understand the benefits of using a framework like Laravel.
- Install a new Laravel project using Composer.
- Learn about Artisan, Laravel's command-line tool.
- Define a route and a controller.
- Use the Eloquent ORM to interact with the database.
- Render a view using the Blade templating engine.
Quick Start
If you want to dive straight in, here's the complete sequence to create a working Laravel blog posts feature:
# Create project and navigate into it
composer create-project laravel/laravel laravel-blog
cd laravel-blog
# Configure SQLite database
echo "DB_CONNECTION=sqlite" >> .env
touch database/database.sqlite
# Generate model, migration, and controller
php artisan make:model Post -m
php artisan make:controller PostController
# Run migrations
php artisan migrate
# Start development server
php artisan serveThen follow the detailed steps below to configure the migration, controller, route, and view. The step-by-step sections will explain what each command does and why.
Step 1: Why Use a Framework?
The simple blog you built in Chapter 19 is great for learning, but a real-world application needs much more:
- A more powerful and flexible router that can handle complex URL parameters, middleware, and API routes
- Robust security features to prevent XSS, CSRF, and SQL injection attacks
- A templating engine with layouts, components, and reusable partials
- A way to manage database schema changes (migrations)
- User authentication and authorization systems
- Form validation, file uploads, email sending, queues, caching, and testing tools
- And much, much more...
A framework like Laravel provides battle-tested solutions for all of these problems out of the box, saving you thousands of hours of development time.
From Scratch to Laravel: A Quick Comparison
Here's how the components you built manually map to Laravel features:
| Your Simple Blog | Laravel Equivalent | What Laravel Adds |
|---|---|---|
$routes array in public/index.php | Route::get() in routes/web.php | Named routes, route parameters, middleware, route grouping, route caching |
Manual require for controllers | Controller classes with dependency injection | Automatic class loading, type-hinted dependencies, resource controllers |
| PDO connection | Eloquent ORM + Query Builder | Object-oriented queries, relationships (one-to-many, many-to-many), eager loading, soft deletes |
Manual include of view files | Blade templating engine | Layouts, components, slots, automatic XSS escaping, view caching |
| No database versioning | Migrations and seeders | Version-controlled schema, easy rollback, shareable database structure |
Manual htmlspecialchars() | Automatic in Blade ({{ }}) | Built-in XSS protection |
| No structure | MVC architecture | Clear separation of concerns, testable code |
This isn't to say your from-scratch blog was bad—far from it! Understanding how to build these components manually gives you deep knowledge of why frameworks work the way they do. You're now in a perfect position to appreciate Laravel's elegance.
Step 1: Install Laravel (~5 min)
Goal
Install Laravel 11 via Composer and confirm the project boots.
Actions
- Create a new Laravel project:
# Create project and navigate into it
composer create-project laravel/laravel laravel-blog
cd laravel-blog- Configure the
.envfile for SQLite (or your preferred database):
echo "DB_CONNECTION=sqlite" >> .env
touch database/database.sqlite- Serve the application to confirm everything runs:
php artisan serveVisit http://127.0.0.1:8000 in your browser and ensure the default Laravel welcome page loads.
Expected Result
The default Laravel homepage appears at http://127.0.0.1:8000, confirming the framework was installed successfully.
Why It Works
composer create-projectdownloads Laravel and all dependencies.- The
.envconfiguration tells Laravel to use SQLite and where the database lives. php artisan servelaunches the built-in PHP development server with Laravel’s routing.
Troubleshooting
composercommand not found — Ensure Composer is installed and available in your PATH.- Permission errors creating the SQLite file — Verify the
database/directory exists and is writable. - Blank page or 500 error — Check
storage/logs/laravel.logfor detailed error messages.
Step 2: Configure the Database (~2 min)
Goal - Set up SQLite as your database and verify Laravel can connect to it.
Laravel is pre-configured to use MySQL, but we can easily switch it to SQLite for simplicity.
Update Environment Configuration
Open the
.envfile in your project root. This file holds your application's environment-specific configuration. Find the database configuration section and update it:bash# filename: .env # Update the DB_CONNECTION line (around line 11) DB_CONNECTION=sqlite # DB_HOST=127.0.0.1 # Comment out or remove # DB_PORT=3306 # Comment out or remove # DB_DATABASE=laravel # Comment out or remove # DB_USERNAME=root # Comment out or remove # DB_PASSWORD= # Comment out or removeCreate the Database File
SQLite uses a single file for the entire database. Create it:
bash# Create an empty SQLite database file touch database/database.sqliteVerify Database Connection
Run a simple Artisan command to test the connection:
bash# Test database connectivity php artisan migrate:statusExpected output:
Migration table not found.This is normal—we haven't run any migrations yet. The important thing is that you didn't get a connection error.
Why it works: The .env file controls which database driver Laravel uses. By setting DB_CONNECTION=sqlite and creating the database file, Laravel knows to use SQLite instead of MySQL. Migrations (which we'll run next) are Laravel's way of managing database schema changes.
Troubleshooting
Problem: "SQLSTATE[HY000]: Unable to open database file"
Solution: Ensure you created the database/database.sqlite file and that the web server has write permissions to the database/ directory.
Step 4: Create the Model and Migration (~3 min)
Goal: Generate a Post model and define the database table schema.
Artisan can generate boilerplate code for us. Let's create a Post model and a database migration file at the same time. A migration is like version control for your database schema.
Generate the Model and Migration
bash# -m flag creates a migration file alongside the model php artisan make:model Post -mExpected output:
INFO Model [app/Models/Post.php] created successfully. INFO Migration [database/migrations/YYYY_MM_DD_HHMMSS_create_posts_table.php] created successfully.Define the Table Schema
Open the newly created migration file in
database/migrations/(it will have a timestamp in the filename). Update theup()method:php# filename: database/migrations/YYYY_MM_DD_HHMMSS_create_posts_table.php <?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('posts', function (Blueprint $table) { $table->id(); $table->string('title'); $table->text('content'); $table->timestamps(); // Automatically creates `created_at` and `updated_at` }); } public function down(): void { Schema::dropIfExists('posts'); } };Run the Migration
Execute the migration to create the
poststable:bash# Run all pending migrations php artisan migrateExpected output:
INFO Running migrations. YYYY_MM_DD_HHMMSS_create_posts_table ............. 15ms DONEVerify Table Creation
You can use Artisan Tinker (Laravel's REPL) to verify:
bashphp artisan tinkerThen run:
php>>> \DB::select('SELECT name FROM sqlite_master WHERE type="table"');You should see
postsin the list. Typeexitto leave Tinker.
Why it works: Migrations allow you to define your database structure using PHP code, making it version-controllable and shareable. The up() method defines what happens when you run the migration, and down() defines how to reverse it.
Troubleshooting
Problem: "Syntax error or access violation: 1071 Specified key was too long"
Solution: This error occurs with MySQL, not SQLite. Ensure your .env file has DB_CONNECTION=sqlite.
Problem: "Nothing to migrate"
Solution: You may have already run migrations. Check php artisan migrate:status to see which migrations have run.
Step 5: Create the Controller (~2 min)
Goal: Generate a controller to handle post-related HTTP requests.
Generate the Controller
bash# Create a new PostController php artisan make:controller PostControllerExpected output:
INFO Controller [app/Http/Controllers/PostController.php] created successfully.Add the Index Method
Open
app/Http/Controllers/PostController.phpand add anindexmethod:php# filename: app/Http/Controllers/PostController.php <?php namespace App\Http\Controllers; use App\Models\Post; class PostController extends Controller { public function index() { // Eloquent query to get all posts, newest first $posts = Post::latest()->get(); return view('posts.index', ['posts' => $posts]); } }
Why it works - Notice how we can use the Post model directly to query the database. This is Laravel's Eloquent ORM in action. The latest() method orders by created_at descending, and get() executes the query. No manual SQL required!
Step 6: Define the Route (~1 min)
Goal: Map a URL path to your controller method.
Add the Route
Open
routes/web.phpand add the following route:php# filename: routes/web.php <?php use App\Http\Controllers\PostController; use Illuminate\Support\Facades\Route; Route::get('/', function () { return view('welcome'); }); // Add this new route Route::get('/posts', [PostController::class, 'index']);
Why it works: The Route::get() method registers a GET route at /posts that will call the index method on PostController. The syntax [PostController::class, 'index'] is modern PHP's way of referencing a class method.
Understanding Laravel's Request Flow
In Chapter 18, you built this flow:
Browser → public/index.php → Router → Controller → view() helper → Layout + ViewLaravel's flow is remarkably similar:
Browser → public/index.php → Laravel's Router → Controller → view() helper → Blade Layout + ViewThe key difference: Laravel's infrastructure is more robust with automatic dependency injection, middleware support, and extensive error handling, but the fundamental pattern is identical to what you built!
Step 7: Create the View (~2 min)
Goal: Build a Blade template to display the list of posts.
Laravel uses a powerful templating engine called Blade. Blade files end in .blade.php and provide a cleaner syntax than raw PHP.
Create the Directory Structure
bash# Create the posts views directory mkdir -p resources/views/postsCreate the View File
Create
resources/views/posts/index.blade.phpwith this content:
# filename: resources/views/posts/index.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>All Posts - Laravel Blog</title>
<style>
body { font-family: sans-serif; max-width: 800px; margin: 50px auto; padding: 0 20px; }
article { border: 1px solid #ddd; padding: 20px; margin-bottom: 20px; border-radius: 5px; }
h1 { color: #333; }
h2 { color: #666; margin-top: 0; }
</style>
</head>
<body>
<h1>All Posts</h1>
@forelse ($posts as $post)
<article>
<h2>{{ $post->title }}</h2>
<p>{{ $post->content }}</p>
<small>Posted on {{ $post->created_at->format('F j, Y') }}</small>
</article>
@empty
<p>No posts yet. Create some posts using Tinker!</p>
@endforelse
</body>
</html>Verify the Route
Visit
http://localhost:8000/postsin your browser. You should see the heading "All Posts" and the message "No posts yet."
Why it works:
@forelseis a Blade directive that combines a foreach loop with an empty check{{ $post->title }}is Blade's syntax for echoing data—it automatically escapes output to prevent XSS attacks (no need forhtmlspecialchars)$post->created_at->format()works because Eloquent automatically casts timestamp columns toCarbonobjects (a powerful date/time library)
Blade vs. Your Layout System
In Chapter 18, you built a layout system using output buffering:
// Your approach in Chapter 18
function view(string $viewName, array $data = [], ?string $layout = 'layout'): void {
ob_start();
require $viewPath;
$content = ob_get_clean();
require $layoutPath; // Layout uses $content variable
}Laravel's Blade uses a different (more elegant) approach with @extends and @section directives:
{{-- resources/views/layouts/app.blade.php --}}
<!DOCTYPE html>
<html>
<head>
<title>@yield('title', 'Laravel Blog')</title>
</head>
<body>
<nav><!-- Navigation --></nav>
@yield('content')
<footer><!-- Footer --></footer>
</body>
</html>
{{-- resources/views/posts/index.blade.php --}}
@extends('layouts.app')
@section('title', 'All Posts')
@section('content')
<h1>All Posts</h1>
@foreach ($posts as $post)
<article>
<h2>{{ $post->title }}</h2>
</article>
@endforeach
@endsectionKey differences:
| Your Approach (Chapter 18) | Laravel's Blade | Advantage |
|---|---|---|
view('home', $data, 'layout') | @extends('layouts.app') | Blade: Declared in the child view, more intuitive |
Layout uses $content variable | Layout uses @yield('content') | Blade: Named sections, can have multiple yield points |
| One content area | Multiple @section/@yield pairs | Blade: Can inject different content into multiple layout slots |
| Output buffering with PHP | Template inheritance | Blade: Compiled to optimized PHP, cached automatically |
Both approaches accomplish the same goal—eliminating duplicate HTML—but Blade's syntax is cleaner and more powerful. You can have separate sections for @yield('sidebar'), @yield('scripts'), etc.
Step 8: Understanding Eloquent Models (~2 min)
Goal: Configure the Post model to work properly with mass assignment.
Before adding data, let's update the Post model to explicitly allow mass assignment of the title and content fields.
Why This Matters
In Chapter 19, you wrote:
Post::create($title, $content); // Passed as individual parametersLaravel's Eloquent uses:
Post::create(['title' => $title, 'content' => $content]); // Passed as arrayThis is called mass assignment. For security, Laravel blocks it by default unless you specify which fields are safe to mass-assign.
Update the Post Model
Open app/Models/Post.php and add the $fillable property:
# filename: app/Models/Post.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = ['title', 'content'];
}Why it works: The $fillable property is a whitelist of attributes that can be mass-assigned. This protects against malicious users trying to set fields like is_admin or user_id through form submissions.
Alternative approach: You can use $guarded instead to blacklist specific fields:
protected $guarded = ['id']; // Everything except 'id' can be mass-assignedChoose $fillable (whitelist) for maximum security, especially when working with user input.
Step 9: Add Sample Data (~3 min)
Goal: Create sample posts to verify everything works end-to-end.
Let's use Tinker, Laravel's interactive PHP shell, to create some posts.
Start Tinker
bashphp artisan tinkerCreate Sample Posts
Run these commands in Tinker:
php>>> use App\Models\Post; >>> Post::create(['title' => 'My First Laravel Post', 'content' => 'Laravel makes building web applications incredibly fast and enjoyable.']); >>> Post::create(['title' => 'Understanding Eloquent', 'content' => 'Eloquent is Laravel\'s ORM that makes database interactions elegant and intuitive.']); >>> Post::create(['title' => 'Blade Templating', 'content' => 'Blade provides a clean and powerful way to build views with minimal PHP code.']); >>> exitExpected output (for each create):
php=> App\Models\Post {#... title: "My First Laravel Post", content: "Laravel makes building web applications...", updated_at: "2024-01-15 10:30:00", created_at: "2024-01-15 10:30:00", id: 1, }Verify in Browser
Refresh
http://localhost:8000/posts. You should now see all three posts displayed with their titles, content, and formatted dates.
Why it works: Eloquent's create() method inserts a new row into the database and returns the model instance. The timestamps() we defined in the migration automatically populate created_at and updated_at.
Troubleshooting
Problem: Posts not showing up after creating them
Solution: Ensure you're viewing the correct URL (http://localhost:8000/posts, not just http://localhost:8000).
Understanding Laravel's Directory Structure
Coming from your simple-blog project in Chapter 19, Laravel's directory structure might look different but follows the same MVC pattern you built.
Directory Comparison
| Your Project (Chapter 18-19) | Laravel Equivalent | Purpose |
|---|---|---|
src/Controllers/ | app/Http/Controllers/ | Controller classes |
src/Models/ | app/Models/ | Eloquent model classes |
src/Views/ | resources/views/ | Blade templates |
src/Routing/Router.php | app/Http/ + routes/ | Routing infrastructure |
src/Core/Database.php | config/database.php + Laravel's DB | Database configuration |
public/index.php | public/index.php | Front controller (entry point) |
data/database.sqlite | database/database.sqlite | SQLite database file |
vendor/ | vendor/ | Composer dependencies |
composer.json | composer.json | Project dependencies |
Key Laravel Directories
app/ - Your application code
app/Http/Controllers/- Controller classesapp/Models/- Eloquent modelsapp/Http/Middleware/- HTTP middleware (authentication, CSRF, etc.)
resources/ - Non-PHP resources
resources/views/- Blade templatesresources/css/- Stylesheetsresources/js/- JavaScript files
routes/ - Route definitions
routes/web.php- Web routes (what you used)routes/api.php- API routes (for REST APIs)routes/console.php- Artisan commands
database/ - Database files
database/migrations/- Database version controldatabase/seeders/- Sample data generatorsdatabase/factories/- Model factories for testing
config/ - Configuration files
config/app.php- Application settingsconfig/database.php- Database connections- And many more...
public/ - Web server document root
public/index.php- Entry point- Static assets (images, compiled CSS/JS)
Why This Structure?
Laravel's structure is more elaborate because it supports many more features out of the box:
- Multiple database connections
- Queue workers for background jobs
- Scheduled tasks (cron jobs)
- API development
- Testing infrastructure
- Broadcasting (WebSockets)
- And much more...
Your simpler structure was perfect for learning the fundamentals!
What Else Laravel Offers
You've only scratched the surface. Here's what Laravel provides beyond what you built:
1. Form Validation
In Chapter 19, you wrote:
$errors = [];
if (empty(trim($title))) {
$errors[] = 'Title is required.';
}Laravel's validation is much more powerful:
$validated = $request->validate([
'title' => 'required|max:255',
'content' => 'required|min:10',
'email' => 'required|email|unique:users',
]);It automatically handles error messages, redirection, and even old input preservation.
2. Relationships Between Models
In Chapter 19, you had a standalone Post model. Laravel makes relationships easy:
// A User has many Posts
class User extends Model {
public function posts() {
return $this->hasMany(Post::class);
}
}
// A Post belongs to a User
class Post extends Model {
public function author() {
return $this->belongsTo(User::class, 'user_id');
}
}
// Usage
$user->posts; // Get all posts by this user
$post->author->name; // Get the author's name3. Authentication Scaffolding
You didn't build authentication, but Laravel includes it:
# Install Laravel Breeze (authentication starter kit)
composer require laravel/breeze --dev
php artisan breeze:install bladeThis gives you login, registration, password reset, email verification, and more—all out of the box.
4. Middleware (What You Learned About in Chapter 17)
In Chapter 17, you learned about middleware conceptually. Laravel implements it:
// Protect routes with authentication
Route::get('/admin', [AdminController::class, 'index'])
->middleware('auth');
// Create custom middleware
php artisan make:middleware CheckAge
// Apply to routes
Route::get('/dashboard', [DashboardController::class, 'index'])
->middleware(['auth', CheckAge::class]);Middleware runs before your controller, perfect for authentication, logging, CORS, etc.
5. Request Objects & Dependency Injection
In Chapter 19, you accessed $_POST directly:
public function store(): void {
$title = $_POST['title'] ?? '';
}Laravel's router automatically injects a Request object:
public function store(Request $request): RedirectResponse {
$validated = $request->validate([...]);
Post::create($validated);
return redirect('/posts')->with('success', 'Post created!');
}This is dependency injection—Laravel automatically provides dependencies to your controller methods. You can type-hint any class (Request, Post, custom services) and Laravel will inject them.
6. Collections
Eloquent returns Collections, not plain arrays:
$posts = Post::all();
// Instead of foreach, use collection methods
$titles = $posts->pluck('title');
$publishedPosts = $posts->filter(fn($post) => $post->is_published);
$sorted = $posts->sortBy('created_at');Collections have 80+ methods for manipulating data elegantly.
7. Artisan Commands
You've used php artisan serve and php artisan make:model. There are dozens more:
php artisan make:controller PostController --resource # CRUD methods
php artisan make:request StorePostRequest # Form request validation
php artisan make:middleware CheckAge # Middleware
php artisan route:list # Show all routes
php artisan tinker # REPL
php artisan migrate:fresh --seed # Reset database with sample dataYou can even create your own custom commands!
8. Testing Support
Laravel includes PHPUnit and a testing API:
public function test_can_create_post(): void
{
$response = $this->post('/posts/store', [
'title' => 'Test Post',
'content' => 'Test content',
]);
$response->assertRedirect('/posts');
$this->assertDatabaseHas('posts', ['title' => 'Test Post']);
}9. Queues for Background Jobs
Send emails, process images, or handle heavy tasks in the background:
// Dispatch a job to the queue
ProcessPodcast::dispatch($podcast);
// Job runs in the background
class ProcessPodcast implements ShouldQueue {
public function handle() {
// Heavy processing here
}
}10. Caching, Sessions, File Storage, and More
Laravel provides unified APIs for:
- Caching (Redis, Memcached, file, database)
- Session management (you used cookies in Chapter 15)
- File storage (local, S3, FTP)
- Email sending (SMTP, Mailgun, SendGrid)
- Event broadcasting (WebSockets via Pusher or Laravel Echo)
All configured through simple config files, swappable without code changes.
The Laravel Ecosystem
Beyond the framework:
- Laravel Forge - Server management and deployment
- Laravel Vapor - Serverless deployment on AWS
- Laravel Nova - Administration panel
- Laravel Cashier - Subscription billing (Stripe, Paddle)
- Laravel Socialite - OAuth authentication (Google, GitHub, etc.)
- Laravel Telescope - Debugging and monitoring tool
- Laravel Horizon - Queue monitoring dashboard
Exercises
Test your understanding by extending the application:
Exercise 1: Show a Single Post
Create a route /posts/{id} that displays a single post. You'll need to:
- Add a new route in
routes/web.phpwith a parameter - Create a
showmethod inPostControllerthat finds a post by ID - Create a
resources/views/posts/show.blade.phpview - Use
Post::findOrFail($id)to retrieve the post (returns 404 if not found)
Exercise 2: Add a Navigation Link
Update resources/views/posts/index.blade.php to add a "Back to Welcome" link at the top that goes to /. Then update the welcome page at resources/views/welcome.blade.php to add a "View Posts" link.
Exercise 3: Style Improvement
The current posts view is very basic. Use Tailwind CSS (which Laravel 11 includes via Vite) or write custom CSS to make the posts page more visually appealing. Consider:
- A card-based layout
- Hover effects on articles
- Better typography
- A responsive design for mobile devices
Exercise 4: Add Post Excerpts
Modify the posts index to show only the first 100 characters of content followed by "..." and a "Read more" link. Hint: Use PHP's substr() function or Blade's Str::limit() helper.
Wrap-up
Congratulations! You've just built your first Laravel application. In less than 30 minutes, you created a working blog post listing feature complete with:
- Database migrations for version-controlled schema changes
- An Eloquent model for clean, object-oriented database interactions
- A controller to handle HTTP requests
- A Blade view with automatic XSS protection
- Sample data to demonstrate the complete workflow
What You Learned
This brief introduction showed you how Laravel's components map directly to the concepts you built from scratch:
| What You Built | Laravel Equivalent | Benefit |
|---|---|---|
| Manual routing array | Route::get() | Powerful route definitions with parameters, middleware, and grouping |
| PDO database connection | Eloquent ORM | Object-oriented queries, relationships, and automatic timestamps |
| Simple view rendering | Blade templating | Layouts, components, and automatic XSS protection |
| Manual SQL queries | Migrations | Version-controlled, shareable database schema |
All the fundamental concepts you learned—OOP, MVC, PSR standards, and database interactions—are the foundation upon which Laravel is built. You now have the knowledge to understand how and why it works, which is the most valuable skill a developer can have.
Next Steps
To continue your Laravel journey:
- Add more features - Try implementing a "show single post" page, a create form, and edit/delete functionality
- Learn authentication - Laravel includes built-in authentication scaffolding with Laravel Breeze or Jetstream
- Explore relationships - Add authors, categories, or comments to your posts using Eloquent relationships
- Deploy your app - Try deploying to platforms like Laravel Forge, Vapor, or standard hosting
In the next chapter, we'll take a quick look at another major framework, Symfony, to see a different approach to solving the same problems.
Code Examples
Exercise solutions from this chapter are available in:
solutions/exercise-1-show-post.php- Single post viewsolutions/exercise-2-navigation.php- Adding navigationsolutions/exercise-3-styling.php- Styling improvementssolutions/exercise-4-excerpts.php- Post excerpts
Note: These are Laravel-specific Blade template examples. The main code for this chapter is your Laravel application created with composer create-project laravel/laravel blog.
Further Reading
- Official Laravel Documentation — Comprehensive and well-written
- Laravel Bootcamp — An official, free tutorial building a complete application
- Laracasts — Video tutorials from beginner to advanced (some free, some paid)
- Laravel News — Stay up-to-date with the Laravel ecosystem
- Eloquent: Getting Started — Deep dive into Laravel's ORM
- Blade Templates — Master the templating engine