← Other topics

Laravel In a Nutshell - Form Processing (#8)

Series contents:

Video Notes

In this guide we’ll explore form processing and validation in Laravel while getting some additional practice using Eloquent models to create new data in our database.

To demonstrate this, we’ll create a “Add a new product” page to our store demo.

Routes

To begin, we’ll start with the addition of two new routes in our /routes/web.php file:

# This first new route will show a form to add a new product
Route::get('/products/create', [ProductsController::class, 'create']);

# This second new route will process the form to add a new product
# Note how the method we’re using here is post instead of get since
# we will be processing a form submitted via the HTTP POST method
Route::post('/products', [ProductsController::class, 'store']);

# This is our existing "Show all the products route"
# Make sure the above routes come before this so they take precedence
# Otherwise, a URL like "/products/create" will be interpreted such that "create" is a category
Route::get('/products/{category?}', [ProductsController::class, 'showProductsByCategory']);

To make the /products/create route accessible to the user, we’ll add a new link to our navigation in main.blade.php:

<nav>
    <ul>
        <li><a href='/products'>Products</a></li>    
        <li><a href='/products/create'>Add New Product</a></li>
        <li><a href='/contact'>Contact</a></li>
    </ul>
</nav>

Show form

To respond to the /products/create route, we’ll set up the following method in ProductsController:

/**
* GET /products/create
*/
public function create() 
{
    # To create a new product we’ll need to present a dropdown of categories
    # that product can be associated with. To do this, we’ll need some category
    # data to pass to the view. 
    # The following query will return an array of category names keyed by their id
    $categories = Category::pluck('name', 'id')->all();

    # Return a view to show our form, including the category data
    return view('products-create')->with('categories', $categories);
}

To support the above method, we’ll create a view at /resources/views/products-create.blade.php with this code:

@extends('main')

@section('page-content')
    <h2>Add New Product</h2>

    <form method='POST' action='/products'>
        @csrf
        <label for='product_name'>Product name:</label>
        <input type='text' name='name' id='product_name'>

        <label for='category_id'>Category:</label>
        <select name='category_id' id='category_id'>
            @foreach ($categories as $id => $name)
                <option value='{{ $id }}'>{{ $name }}</option>
            @endforeach
        </select>

        <button type='submit'>Add new product</button>
    </form>
@endsection

Resulting form:

Process form

The above form submits to our /products POST route, which will invoke a store method in our ProductsController that will look like this:

/**
 * POST /products
 */
public function store(Request $request)
{
    # Set up a new instance of our Product model to perist the new product to the database
    # Note how the form data is accessed via the $request object that is passed to this method
    $product = new Product();
    $product->name = $request->name;
    $product->category_id = $request->category_id;
    $product->save();

    # When done, redirect the user back and include a message we 
    # can display on the page as confirmation
    return redirect('/products/create')->with(
        'message',
        'Your product ' . $product->name . ' was added'
    );
}

To output the message that is flashed as part of the redirect we’ll add the following code after our form element in /resources/view/products-create.blade.php:

@if (session('message'))
    {{ session('message') }}
@endif

Result after adding a new product:

Validation

After completing the above steps, we should have a working feature that allows visitors to add new products. To wrap things up, we’ll sprinkle in some basic form validation as shown in the following updated store method code:

/**
 * POST /products
 */
public function store(Request $request)
{
    # ⭐ NEW ⭐
    $request->validate([
        'name' => 'required|unique:products|max:255',
    ]);

    $product = new Product();
    $product->name = $request->name;
    $product->category_id = $request->category_id;
    $product->save();

    return redirect('/products/create')->with(
        'message',
        'Your product ' . $product->name . ' was added'
    );
}

To output any errors caught in validation, add the following code after your form in products-create.blade.php:

@if ($errors->any())
    <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
    </ul>
@endif

Result:

If this info helped you out, you can send a tip via PayPal. Thanks for your support!
← Other topics