When I first started working with Laravel, handling multi-step forms felt overwhelming. I wanted to create a form that could collect user data across multiple steps, validate each step, and store it securely without confusing the user. After experimenting, I discovered that Laravel’s validation and session features make this process straightforward.
In this article, I’ll share a simple, beginner-friendly guide on how to build and validate a multi-step form in Laravel. Whether you’re creating a registration form or a complex survey, this step-by-step guide will help you get it done efficiently.
To get started, I create a new Laravel project using Composer. If you don’t have Laravel installed, run this command in your terminal:
composer create-project laravel/laravel multi-step-form
Once the project is set up, I navigate to the project directory and ensure my database is configured in the .env
file. For this example, I’ll use MySQL, but you can use any database Laravel supports.
Next, I create a model and migration for storing form data. For this example, let’s assume I’m building a user registration form with fields like name, email, phone, and address split across multiple steps.
Run this command to create a UserDetail
model with a migration:
php artisan make:model UserDetail -m
In the migration file (located in database/migrations
), I define the schema:
Schema::create('user_details', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('phone')->nullable();
$table->string('address')->nullable();
$table->timestamps();
});
Then, I run the migration:
php artisan migrate
I define routes to handle each step of the form. In routes/web.php
, I add:
use App\Http\Controllers\FormController;
Route::get('/form/step1', [FormController::class, 'showStep1'])->name('form.step1');
Route::post('/form/step1', [FormController::class, 'postStep1'])->name('form.step1.post');
Route::get('/form/step2', [FormController::class, 'showStep2'])->name('form.step2');
Route::post('/form/step2', [FormController::class, 'postStep2'])->name('form.step2.post');
Route::get('/form/confirmation', [FormController::class, 'confirmation'])->name('form.confirmation');
I create a controller to handle the form logic:
php artisan make:controller FormController
In app/Http/Controllers/FormController.php
, I add methods to display and process each step. Here’s a simplified version:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\UserDetail;
use Illuminate\Support\Facades\Session;
class FormController extends Controller
{
// Show Step 1
public function showStep1()
{
return view('form.step1');
}
// Process Step 1
public function postStep1(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:user_details,email',
]);
// Store data in session
Session::put('form_data', $request->only('name', 'email'));
return redirect()->route('form.step2');
}
// Show Step 2
public function showStep2()
{
return view('form.step2');
}
// Process Step 2
public function postStep2(Request $request)
{
$request->validate([
'phone' => 'nullable|string|max:15',
'address' => 'nullable|string|max:255',
]);
// Merge step 2 data with session data
$formData = Session::get('form_data');
$formData = array_merge($formData, $request->only('phone', 'address'));
// Save to database
UserDetail::create($formData);
// Clear session
Session::forget('form_data');
return redirect()->route('form.confirmation');
}
// Show Confirmation
public function confirmation()
{
return view('form.confirmation');
}
}
I create Blade views for each step in the resources/views/form
directory.
Step 1 (step1.blade.php
):
<!DOCTYPE html>
<html>
<head>
<title>Step 1 - Multi-Step Form</title>
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div class="container">
<h2>Step 1: Personal Information</h2>
<form method="POST" action="{{ route('form.step1.post') }}">
@csrf
<div>
<label>Name</label>
<input type="text" name="name" value="{{ old('name') }}">
@error('name') <span>{{ $message }}</span> @enderror
</div>
<div>
<label>Email</label>
<input type="email" name="email" value="{{ old('email') }}">
@erroremail') <span>{{ $message }}</span> @enderror
</div>
<button type="submit">Next</button>
</form>
</div>
</body>
</html>
Step 2 (step2.blade.php
):
<!DOCTYPE html>
<html>
<head>
<title>Step 2 - Multi-Step Form</title>
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div class="container">
<h2>Step 2: Contact Information</h2>
<form method="POST" action="{{ route('form.step2.post') }}">
@csrf
<div>
<label>Phone</label>
<input type="text" name="phone" value="{{ old('phone') }}">
@error('phone') <span>{{ $message }}</span> @enderror
</div>
<div>
<label>Address</label>
<input type="text" name="address" value="{{ old('address') }}">
@error('address') <span>{{ $message }}</span> @enderror
</div>
<button type="submit">Submit</button>
</form>
</div>
</body>
</html>
Confirmation (confirmation.blade.php
):
<!DOCTYPE html>
<html>
<head>
<title>Form Submitted</title>
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div class="container">
<h2>Thank You!</h2>
<p>Your form has been submitted successfully.</p>
</div>
</body>
</html>
To make the form look clean, I add some basic CSS in resources/css/app.css
:
.container {
max-width: 600px;
margin: 50px auto;
padding: 20px;
}
form div {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input {
width: regno:1px;
padding: 8px;
border: 1px solid #ccc;
}
span {
color: red;
}
button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
}
Then, I compile the CSS:
npm install && npm run dev
I start the Laravel server:
php artisan serve
Then, I visit http://localhost:8000/form/step1
to test the form. I fill out each step, check for validation errors, and ensure the data is saved to the database.
Building a multi-step form in Laravel was easier than I expected, thanks to Laravel’s powerful validation and session management features. By breaking the form into steps, storing data in sessions, and validating each step, I created a user-friendly experience that’s both secure and efficient. This approach is perfect for complex forms like registrations or surveys. With this guide, you can create your own multi-step form and customize it to fit your project’s needs.
1. Why use a multi-step form instead of a single form?
Multi-step forms break down long forms into smaller, manageable steps, improving user experience and reducing form abandonment.
2. How do I prevent users from skipping steps?
You can use middleware or session checks in your controller to ensure users complete each step in order before proceeding.
3. Can I add more steps to the form?
Yes, simply add more routes, controller methods, and views for additional steps, following the same session-based approach.
4. How do I handle validation errors in multi-step forms?
Laravel’s validation system automatically returns errors to the view, which you can display using @error
directives in Blade templates.
5. Is it secure to store form data in sessions?
Yes, Laravel’s session handling is secure, but ensure sensitive data is encrypted or cleared after submission for added security.
You might also like :