In this tutorial, we are going to learn how to implement Multi Step Form in Laravel. When you need to add something without single step you can use this method to add it through multiple steps.

Prerequisites

  • Laravel
  • To Continue with this tutorial, you should have installed Laravel 8 in your pc. If you are still not installed Laravel in your machine you can configure it from here.

    Setting up the Project

    First you need to create a new laravel project by running below command in your terminal
    1
    composer create-project laravel/laravel laravel-multistep

    Then navigate to your project directory by using below command in your terminal

    1
    cd laravel-multistep

    Setting up Database

    To setup up Database for our project, open the application using your favourite text editor and and then navigate to .env file in it and then change below section acording to your Database settings:

    1
    2
    3
    4
    5
    6
    DB_CONNECTION=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=laravel-multistep
    DB_USERNAME=root
    DB_PASSWORD=

    Create Migration

    Now, we need to create our migration file for product table. To create migration file run below command in your terminal:
    1
    php artisan make:migration create_products_table

    Then navigate to your product migration file and add below code on it:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?php

    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;

    class CreateProductsTable extends Migration
    {
    public function up()
    {
    Schema::create('products', function (Blueprint $table) {
    $table->id();
    $table->string('name')->nullable();
    $table->longText('description')->nullable();
    $table->float('amount')->nullable();
    $table->boolean('status')->default(0);
    $table->integer('stock')->default(0);
    $table->timestamps();
    });
    }

    public function down()
    {
    Schema::dropIfExists('products');
    }
    }

    Then run below command in your terminal to migrate our newly created product migration file:

    1
    php artisan migrate

    Create Models

    Now we need to create Product model. To create Product model run below command in your terminal:
    1
    php artisan make:model Product

    Then navigate to Product model and paste below code on it.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Product extends Model
    {
    protected $fillable = [
    'name',
    'amount',
    'description',
    'status',
    'stock'
    ];
    }

    Create Product Controller

    Now we need to create contoller to handle our core logic for handling our Datata and views. To create new controller:
    1
    php artisan make:controller ProductController

    After that open your app/Http/Controllers/ProductController.php and paste below code in it:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    <?php

    namespace App\Http\Controllers;

    use Illuminate\Http\Request;

    use App\Product;

    class ProductController extends Controller
    {
    public function index()
    {
    $products = Product::all();
    return view('products.index',compact('products'));
    }

    public function createStepOne(Request $request)
    {
    $product = $request->session()->get('product');
    return view('products.create-step-one',compact('product'));
    }

    public function postCreateStepOne(Request $request)
    {
    $validatedData = $request->validate([
    'name' => 'required|unique:products',
    'amount' => 'required|numeric',
    'description' => 'required',
    ]);

    if(empty($request->session()->get('product'))){
    $product = new Product();
    $product->fill($validatedData);
    $request->session()->put('product', $product);
    }else{
    $product = $request->session()->get('product');
    $product->fill($validatedData);
    $request->session()->put('product', $product);
    }

    return redirect()->route('products.create.step.two');
    }

    public function createStepTwo(Request $request)
    {
    $product = $request->session()->get('product');
    return view('products.create-step-two',compact('product'));
    }

    public function postCreateStepTwo(Request $request)
    {
    $validatedData = $request->validate([
    'stock' => 'required',
    'status' => 'required',
    ]);

    $product = $request->session()->get('product');
    $product->fill($validatedData);
    $request->session()->put('product', $product);

    return redirect()->route('products.create.step.three');
    }

    public function createStepThree(Request $request)
    {
    $product = $request->session()->get('product');
    return view('products.create-step-three',compact('product'));
    }

    public function postCreateStepThree(Request $request)
    {
    $product = $request->session()->get('product');
    $product->save();

    $request->session()->forget('product');
    return redirect()->route('products.index');
    }
    }

    Create Views

    Inside resources -> views folder create, folder called layouts. Then create an app.blade.php file inside i and add the following code.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!DOCTYPE html>
    <html>
    <head>
    <title>Laravel Multi Step Form Example</title>
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" />
    </head>
    <body style="background-color: #f3fdf3">

    <div class="container">
    @yield('content')
    </div>

    </body>

    </html>

    Then create folder call prodct in your view folder and add below codes on them.

  • Index.blade.php
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    @extends('layouts.app')

    @section('content')
    <div class="container">
    <div class="row justify-content-center">
    <div class="col-md-10">
    <div class="card">
    <div class="card-header">Manage Product</div>

    <div class="card-body">

    <a href="{{ route('products.create.step.one') }}" class="btn btn-primary pull-right">Create Product</a>

    @if (Session::has('message'))
    <div class="alert alert-info">{{ Session::get('message') }}</div>
    @endif
    <table class="table">
    <thead class="thead-dark">

    </thead>
    <tbody>
    @foreach($products as $product)
    <tr>
    <th scope="row">{{$product->id}}</th>
    <td>{{$product->name}}</td>
    <td>{{$product->description}}</td>
    <td>{{$product->stock}}</td>
    <td>{{$product->amount}}</td>
    <td>{{$product->status ? 'Active' : 'DeActive'}}</td>
    </tr>
    @endforeach
    </tbody>
    </table>
    </div>
    </div>
    </div>
    </div>
    </div>
    @endsection
  • create-step-one.blade.php
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    @extends('layouts.app')
    @section('content')
    <div class="container">
    <div class="row justify-content-center">
    <div class="col-md-10">
    <form action="{{ route('products.create.step.one.post') }}" method="POST">
    @csrf

    <div class="card">
    <div class="card-header">Step 1: Basic Info</div>

    <div class="card-body">

    @if ($errors->any())
    <div class="alert alert-danger">
    <ul>
    @foreach ($errors->all() as $error)
    <li>{{ $error }}</li>
    @endforeach
    </ul>
    </div>
    @endif

    <div class="form-group">
    <label for="title">Product Name:</label>
    <input type="text" value="{{ $product->name ?? '' }}" class="form-control" id="taskTitle" name="name">
    </div>
    <div class="form-group">
    <label for="description">Product Amount:</label>
    <input type="text" value="{{{ $product->amount ?? '' }}}" class="form-control" id="productAmount" name="amount" />
    </div>

    <div class="form-group">
    <label for="description">Product Description:</label>
    <textarea type="text" class="form-control" id="taskDescription" name="description">{{{ $product->description ?? '' }}}</textarea>
    </div>

    </div>

    <div class="card-footer text-right">
    <button type="submit" class="btn btn-primary">Next</button>
    </div>
    </div>
    </form>
    </div>
    </div>
    </div>
    @endsection
  • create-step-two.blade.php
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    @extends('layouts.app')

    @section('content')
    <div class="container">
    <div class="row justify-content-center">
    <div class="col-md-10">
    <form action="{{ route('products.create.step.two.post') }}" method="POST">
    @csrf
    <div class="card">
    <div class="card-header">Step 2: Status & Stock</div>

    <div class="card-body">

    @if ($errors->any())
    <div class="alert alert-danger">
    <ul>
    @foreach ($errors->all() as $error)
    <li>{{ $error }}</li>
    @endforeach
    </ul>
    </div>
    @endif

    <div class="form-group">
    <label for="description">Product Status</label><br />
    <label class="radio-inline"><input type="radio" name="status" value="1" {{{ (isset($product->status) && $product->status == '1') ? "checked" : "" }}}> Active</label>
    <label class="radio-inline"><input type="radio" name="status" value="0" {{{ (isset($product->status) && $product->status == '0') ? "checked" : "" }}}> DeActive</label>
    </div>

    <div class="form-group">
    <label for="description">Product Stock</label>
    <input type="text" value="{{{ $product->stock ?? '' }}}" class="form-control" id="productAmount" name="stock" />
    </div>

    </div>
    <div class="card-footer">
    <div class="row">
    <div class="col-md-6 text-left">
    <a href="{{ route('products.create.step.one') }}" class="btn btn-danger pull-right">Previous</a>
    </div>
    <div class="col-md-6 text-right">
    <button type="submit" class="btn btn-primary">Next</button>
    </div>
    </div>
    </div>
    </div>
    </form>
    </div>
    </div>
    </div>
    @endsection
  • create-step-three.blade.php
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    @extends('layouts.app')
    @section('content')
    <div class="container">
    <div class="row justify-content-center">
    <div class="col-md-10">
    <form action="{{ route('products.create.step.three.post') }}" method="post">
    {{ csrf_field() }}
    <div class="card">
    <div class="card-header">Step 3: Review Details</div>

    <div class="card-body">

    <table class="table">
    <tr>
    <td>Product Name:</td>
    <td><strong>{{$product->name}}</strong></td>
    </tr>
    <tr>
    <td>Product Amount:</td>
    <td><strong>{{$product->amount}}</strong></td>
    </tr>
    <tr>
    <td>Product status:</td>
    <td><strong>{{$product->status ? 'Active' : 'DeActive'}}</strong></td>
    </tr>
    <tr>
    <td>Product Description:</td>
    <td><strong>{{$product->description}}</strong></td>
    </tr>
    <tr>
    <td>Product Stock:</td>
    <td><strong>{{$product->stock}}</strong></td>
    </tr>
    </table>
    </div>
    <div class="card-footer">
    <div class="row">
    <div class="col-md-6 text-left">
    <a href="{{ route('products.create.step.two') }}" class="btn btn-danger pull-right">Previous</a>
    </div>
    <div class="col-md-6 text-right">
    <button type="submit" class="btn btn-primary">Submit</button>
    </div>
    </div>
    </div>
    </div>
    </form>
    </div>
    </div>
    </div>
    @endsection

    Define Routes

    Navigate to routes/web.php file and paste below code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <?php

    use Illuminate\Support\Facades\Route;


    Route::get('/', function () {
    return view('welcome');
    });

    Route::get('products', 'ProductController@index')->name('products.index');

    Route::get('products/create-step-one', 'ProductController@createStepOne')->name('products.create.step.one');
    Route::post('products/create-step-one', 'ProductController@postCreateStepOne')->name('products.create.step.one.post');

    Route::get('products/create-step-two', 'ProductController@createStepTwo')->name('products.create.step.two');
    Route::post('products/create-step-two', 'ProductController@postCreateStepTwo')->name('products.create.step.two.post');

    Route::get('products/create-step-three', 'ProductController@createStepThree')->name('products.create.step.three');
    Route::post('products/create-step-three', 'ProductController@postCreateStepThree')->name('products.create.step.three.post');

    Run our application

    Now we have already finished our application. Now we can run your application using below command:
    1
    php artisan serve

    Now, navigate to http://localhost:8000 in your browser.

    Conclusion

    In this tutorial, we implemented Multistep Form in Laravel. If you have any issue regarding this tutorial, mention your issue in comment section or reach me through my E-mail. You can obtain complete source code and asset files for this tutorial from this GitHub repository.