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: