PHP Laravel Basics — Complete Beginner's Guide to the Laravel Framework
In this tutorial, you will learn about PHP Laravel Basics. We cover key concepts, practical examples, and best practices to help you master this topic.
Laravel is the most popular PHP web framework, providing an elegant syntax for routing, database access, templating, and authentication that accelerates development of modern web applications. This tutorial covers installing Laravel, understanding the MVC architecture, defining routes and controllers, building Blade templates, modeling data with Eloquent ORM and migrations, and using Artisan commands to scaffold code.
What You'll Learn
- Installing Laravel via Composer and configuring the environment file
- Understanding the MVC directory structure and request lifecycle
- Defining web routes, route parameters, and named routes
- Creating controllers and organizing logic with resource controllers
- Building Blade templates with layouts, components, and directives
- Using Eloquent ORM for database queries, relationships, and migrations
- Leveraging Artisan for code generation and maintenance
Why It Matters
Laravel handles the repetitive parts of web development: routing, session management, CSRF protection, database abstraction, and authentication. Instead of writing boilerplate code for every project, you focus on the business logic. Laravel also enforces best practices like dependency injection, testing, and Separation Of Concerns through its MVC architecture, making your code maintainable and scalable.
Real-World Use
Doda Browser's account dashboard is built with Laravel. The framework's built-in Rate Limiting protects the API from abuse, Eloquent queries the user database efficiently, and Blade renders pages with consistent layouts. Laravel Queues handle email notifications asynchronously, keeping the UI responsive even during high traffic.
Learning Path
flowchart LR A[PSR Standards] --> B[Laravel Basics\nYou are here] B --> C[Symfony Basics] style B fill:#f90,color:#fff
Installing Laravel
Create a new Laravel project:
composer create-project laravel/laravel my-app
cd my-app
Start the development server:
php artisan serve
Output:
INFO Server running on [http://127.0.0.1:8000].
Open http://127.0.0.1:8000 in your browser. You should see the Laravel welcome page.
Directory Structure
Key directories in a Laravel project:
| Directory | Purpose |
|---|---|
app/Http/Controllers/ |
Controller classes that handle HTTP requests |
app/Models/ |
Eloquent model classes for database tables |
database/migrations/ |
Database schema definition files |
resources/views/ |
Blade template files |
routes/ |
Route definitions (web.php, api.php, console.php) |
config/ |
Application configuration files |
Defining Routes
Open routes/web.php:
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
Route::get('/hello/{name}', function (string $name) {
return "Hello, $name! Welcome to Laravel.";
});
Route::get('/products/{category}/{id}', function (string $category, int $id) {
return "Category: $category, Product ID: $id";
})->where(['id' => '[0-9]+']);
Test with the browser or curl:
curl http://127.0.0.1:8000/hello/Alice
curl http://127.0.0.1:8000/products/electronics/42
Output:
Hello, Alice! Welcome to Laravel.
Category: electronics, Product ID: 42
Creating Controllers
Generate a controller with Artisan:
php artisan make:controller ProductController
This creates app/Http/Controllers/ProductController.php:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProductController extends Controller
{
public function index(): string
{
return 'List all products';
}
public function show(int $id): string
{
return "Show product with ID: $id";
}
public function store(Request $request): string
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'price' => 'required|numeric|min:0',
]);
return "Product created: {$validated['name']}";
}
}
Register routes for the controller in routes/web.php:
<?php
use App\Http\Controllers\ProductController;
use Illuminate\Support\Facades\Route;
Route::get('/products', [ProductController::class, 'index']);
Route::get('/products/{id}', [ProductController::class, 'show'])->whereNumber('id');
Route::post('/products', [ProductController::class, 'store']);
Use a resource controller for CRUD operations:
php artisan make:controller UserController --resource
<?php
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;
Route::resource('/users', UserController::class);
This registers seven routes: index, create, store, show, edit, update, and destroy.
Blade Templates
Blade is Laravel's template engine. Create resources/views/layouts/app.blade.php:
<!DOCTYPE html>
<html>
<head>
<title>@yield('title', 'Laravel App')</title>
</head>
<body>
<header>
<h1>Laravel Demo</h1>
<nav>
<a href="{{ url('/') }}">Home</a>
<a href="{{ url('/products') }}">Products</a>
</nav>
</header>
<main>
@yield('content')
</main>
</body>
</html>
Create resources/views/products.blade.php:
@extends('layouts.app')
@section('title', 'Products')
@section('content')
<h2>Our Products</h2>
<ul>
@foreach ($products as $product)
<li>{{ $product['name'] }} - ${{ $product['price'] }}</li>
@endforeach
</ul>
@endsection
Update the controller to return the view:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProductController extends Controller
{
public function index()
{
$products = [
['name' => 'Laptop', 'price' => 999],
['name' => 'Phone', 'price' => 699],
['name' => 'Tablet', 'price' => 399],
];
return view('products', ['products' => $products]);
}
}
Eloquent ORM and Migrations
Generate a Migration and model:
php artisan make:model Product -m
Edit the migration at database/migrations/xxxx_create_products_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('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->decimal('price', 8, 2);
$table->text('description')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('products');
}
};
Run the migration:
php artisan migrate
Output:
INFO Running migrations.
xxxx_xx_xx_xxxxxx_create_products_table ............................................... 32ms DONE
Use the model in a controller:
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
public function index()
{
$products = Product::all();
return view('products', ['products' => $products]);
}
public function store(Request $request)
{
$product = Product::create($request->validate([
'name' => 'required|string|max:255',
'price' => 'required|numeric|min:0',
]));
return redirect('/products');
}
}
Common Mistakes
- Not using Artisan for generation: Hand-writing controllers, models, and migrations is error-prone. Artisan generates correct boilerplate and places files in the right directories.
- Putting business logic in routes: Route closures should be minimal. Move logic to controllers or service classes for testability and reuse.
- Forgetting to run migrations after model changes: If you add a column to a migration but do not run
php artisan migrate, the database schema does not match the model. - Using raw SQL instead of Eloquent: Eloquent provides query building, relationship loading, and eager loading. Raw SQL negates Laravel's database abstraction benefits.
- Ignoring CSRF protection: All POST requests in Laravel require a CSRF token. Use
@csrfin Blade forms and include the token in AJAX requests using the meta tag.
Practice Questions
What is the purpose of
php artisan serve?- It starts a local development server on
127.0.0.1:8000for testing without configuring Apache or Nginx.
- It starts a local development server on
How do you define a route that accepts a numeric ID?
- Use a route parameter with a where constraint:
Route::get('/products/{id}', ...)->whereNumber('id').
- Use a route parameter with a where constraint:
What is Blade's
@yielddirective used for?- It defines a section in a layout that child templates fill using
@section. This creates reusable page layouts.
- It defines a section in a layout that child templates fill using
How do you create a database table in Laravel?
- Generate a migration with
php artisan make:migration, define the schema in theupmethod, and runphp artisan migrate.
- Generate a migration with
Challenge: Build a blog application with Laravel that has posts, categories, and comments. Use Eloquent relationships (hasMany, belongsTo) and display nested comments in Blade.
Mini Project
Create a product review system with Laravel:
- Use a resource controller for Review management.
- Create migrations for products, reviews, and users tables.
- Define Eloquent relationships: a product has many reviews; a review belongs to a user.
- Build Blade templates for listing products, viewing a product with reviews, and submitting a review form.
- Add validation: review rating must be 1-5, title is required, body is optional.
- Implement authentication with Laravel Breeze or the built-in auth scaffolding.
FAQ
What's Next
Laravel is one option. Learn the other major PHP framework with Symfony Basics.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro