How to Use the Same Form for Create and Update in Laravel
If you have to develop create and update forms in Laravel, you can use a single blade file for create and update instead of, creating two different blade files. We can use the same form for Add and Edit. In this case, you maintain only one blade file without adding complexity to the form.
We will develop a demo application to show this. We will show a list of product categories, add a new category and update an existing category. We will use the same form both add category and update category.
Laravel project
Create a Laravel project using the below command, project name is lara_form:
composer create-project --prefer-dist laravel/laravel lara_form
Laravel Migration
We will use a MySQL database named 'lara_form', so will update the .env
file as below:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=lara_form
DB_USERNAME=root
DB_PASSWORD=
We will create a custom table called 'categories' to store product categories. Let us create a migration for this table along with the model:
php artisan make:model Category -m
Open the migration file for the categories table and update the up()
method as below:
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('descr');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('categories');
}
We are creating a new table called 'categories' with the columns 'name' and 'descr'
.
Run the Laravel migration to create our custom table and the default tables for Laravel:
php artisan migrate
After running the migration, below tables will be created:
Update the Model
The Category model is already created, let us update it to add $fillable columns. In our case, these are the 'name' and 'descr' columns.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
protected $fillable = ['name', 'descr'] ;
}
Create a Resource Controller
We will create a resource controller named "CategoryController". The resource controller will create the methods we need for our demo application. index(), create(), store(), edit()
and update()
methods will be available in our controller.
Run the below command from the terminal to create the resource controller:
php artisan make:controller CategoryController --resource
Create a Resource Route
Add a resource route in web.php, we will give the name as category.
Route::resource("category", CategoryController::class);
The following routes will be available for us:
We will show a list of all product categories in one view. Within this view, we will have an Edit button for each category. Also, the same view will have an Add button to add a new category.
Let us write the code for index(), create(), store(), edit()
and update()
methods in the controller.
index()
method will select all rows from the categories table and call the view 'index' to show a list of all categories.
create()
method will be used to add a category and uses the view 'add_category'. Add category form will have only two input fields - category name and description.
store()
method will validate the form data and insert a row in the categories table.
edit()
method will be used to edit the category name and description, it will call the same view 'add_category' for the edit form.
update()
method will update the category name and description.
So, we will have two views - index and add_category. The add_category view will be used for both the add and edit categories.
Methods in the controller are given below:
public function index()
{
$cat = Category::orderBy("name","asc")->get();
return view('index', compact('cat'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('add_category');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$request->validate(
[
'name' => 'required',
'descr' => 'required',
],
[
'name.required'=> 'Please enter a name',
'descr.required'=> 'Please enter a description',
]
);
try{
Category::create($request->only('name', 'descr'));
return redirect()->route('category.index')->withSuccess('Product Category added successfully');
}
catch(\Exception $e){
return back()->withError($e->getMessage())->withInput();
}
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
$edit = Category::findOrFail($id);
return view('add_category', compact('edit'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
$request->validate(
[
'name' => 'required',
'descr' => 'required',
],
[
'name.required'=> 'Please enter a name',
'descr.required'=> 'Please enter a description',
]
);
try{
Category::where('id',$id)->update($request->only('name', 'descr'));
return redirect()->route('category.index')->withSuccess('Product Category updated successfully');
}
catch(\Exception $e){
return back()->withError($e->getMessage())->withInput();
}
}
In the store()
method, if a category is added successfully, the user is redirected to the index page with a success message. But, in case of an error, an error message is displayed and the user stays on the same page. This is true for update()
method as well.
Laravel blade views for add and update forms
We will use two views, an index view and a view for add and update categories. Below are the views along with the layout:
resources/views/layouts/header.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Use the same form for create and update in Laravel</title>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
<meta name="_token" content="{{ csrf_token() }}">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" media="screen" href="{{ asset('css/style.css') }}" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
resources/views/layouts/master.blade.php
@include('layouts.header')
<body>
<h1>Use the same form for create and update in Laravel</h1>
@yield('main-content')
</body>
</html>
Add and Edit View
Since we will be using the same view for Add and Edit, we need to add some code in the Add form so that we can use it as an update form also.
Heading for the form
We need to use if...else
here to check if the view is called for edit or add. For edit mode we will have a category ID value set, we will use the below code to give a heading for the form.
<h2>{{ isset($edit->id) ? 'Update Product Category' : 'Add Product Category' }}</h2>
This means that if the category id is available, then use the form heading "Update Product Category", else use "Add Product Category". In the same way, we will use the appropriate routes for the form action and the input value. See below:
Form Action
@if (isset($edit->id))
<form class="form1" method="post" action="{{ route('category.update', $edit->id) }}">
@method('PUT')
@else
<form class="form1" method="post" action="{{ route('category.store') }}">
@endif
Form Input Value
<input class="form-control mt-2" type="text" name="name" placeholder="Enter Category Name"
value="{{ old('name', isset($edit->id) ? $edit->name : '') }}">
Below is the complete code for add_category view:
resources/views/add_category.blade.php
@extends('layouts.master')
@section('main-content')
<div class="container">
<div class="text-end"><a href="{{ route('category.index') }}"><button class="btn btn-primary"><i class="fa fa-list"></i>
Product Category List</button></a></div>
<h2>{{ isset($edit->id) ? 'Update Product Category' : 'Add Product Category' }}</h2>
@if (session('error'))
<div class="alert alert-danger">
{{ session('error') }}
</div>
@endif
@if (isset($edit->id))
<form class="form1" method="post" action="{{ route('category.update', $edit->id) }}">
@method('PUT')
@else
<form class="form1" method="post" action="{{ route('category.store') }}">
@endif
@csrf
<div class="form-group col-md-12 mb-3">
<label for="">Category Name</label>
<input class="form-control mt-2" type="text" name="name" placeholder="Enter Category Name"
value="{{ old('name', isset($edit->id) ? $edit->name : '') }}">
@error('name')
<div class="error">{{ $message }}</div>
@enderror
</div>
<div class="form-group col-md-12 mb-3">
<label for="">Description</label>
<input class="form-control mt-2" type="text" name="descr" placeholder="Enter Description"
value="{{ old('descr', isset($edit->id) ? $edit->descr : '') }}">
@error('descr')
<div class="error">{{ $message }}</div>
@enderror
</div>
<input type="submit" class="btn btn-primary" value="Submit">
<a class="btn btn-danger" href="{{ route('category.index') }}">Cancel</a>
</form>
</div>
@endsection
Below is the stylesheet:
table{
margin: auto;
}
table>thead{
background-color:#2b5171;
color:#fff;
}
h1, h2{
text-align: center;
}
.form1{
width:50%;
margin:30px auto;
}
.container{
width:70%;
}
.error{
color:red;
}
Test the application
From the project root, start the php development server:
php artisan serve
From the browser run localhost:8000/category
. You will see a list of categories displayed, you will not have the data in the table initially, so, you will see "No Data found". Click on the Add Category button and add a new category. You will see the new category added to the list. Now update the same and check if everything is working fine.
Download Source code from Github.
Post a Comment