CRUD – Create, Read, Update and Delete is essential functionality for almost every web application. With help of laravel, this can be easily done through some functionalities like resource controller and route model binding that ships with laravel out of the box. In this blog, we are going to perform simple crud operation for user module. This blog is mainly written for laravel beginners to kickstart their laravel journey.
Installing Laravel
First things first. Let us install fresh laravel application by the following.
With Laravel Installer
laravel new crud
With Composer
composer create-project --prefer-dist laravel/laravel crud
Once that is done, configure your .env file for database connectivity and then boot our application with
php artisan serve
Now you should be seeing laravel home page.
Migration
Lets create database tables by migrating default migration files that ships with laravel
php artisan migrate
Basic Authentication
We are going to use laravel’s inbuilt authentication system so that we will get nice bootstrap template setup.
php artisan make:auth
To know more about how authentication system works, check out
authentication quickstart Now, your homepage will look like this.
You can go ahead and create a user for yourself to login into the system.
HTML Collective
In this tutorial, we are going to use laravel html collective for easier form handling. You can checkout its documentation
here and install the package.
Create Controller
First, we need to create a resource controller.
php artisan make:controller UserController --resource
Above command will generate
UserController along with index, create, store, show, edit, update and destroy functions like the following
namespace App\Http\Controllers; |
use Illuminate\Http\Request; |
class UserController extends Controller |
* Display a listing of the resource. |
* @return \Illuminate\Http\Response |
* Show the form for creating a new resource. |
* @return \Illuminate\Http\Response |
* Store a newly created resource in storage. |
* @param \Illuminate\Http\Request $request |
* @return \Illuminate\Http\Response |
public function store(Request $request) |
* Display the specified resource. |
* @return \Illuminate\Http\Response |
public function show($id) |
* Show the form for editing the specified resource. |
* @return \Illuminate\Http\Response |
public function edit($id) |
* Update the specified resource in storage. |
* @param \Illuminate\Http\Request $request |
* @return \Illuminate\Http\Response |
public function update(Request $request, $id) |
* Remove the specified resource from storage. |
* @return \Illuminate\Http\Response |
public function destroy($id) |
If you give only controller name and not –resource then you will get plain controller file without any functions.
Quick Tip:
If you want to create a resource controller inside a folder say, inside Admin folder, you can achieve this by specifying the folder name before the controller name. For example like this
php artisan make:controller Admin/UserController --resource
Routes
Now that we have user resource controller setup, lets add our route configuration. As mentioned earlier, we are going to use laravel’s resource controller and route model binding.
Route::resource('users', 'UserController');
If you never came across laravel resource controller, checkout laravel documentation
hereRoute Model Binding
Laravel provides a convenient way to inject model instance to routes that are binded with model. This can be done in two ways.
- Implicit Binding
- Explicit Binding
But we are going to see only explicit binding here. I may cover an article about implicit binding in coming days. You can also learn it through
laravel documentation For explicit binding, look for
app\Providers\RouteServiceProvider file. Inside the boot function add the following line
$router->model('users', '\App\User');
Menu
First, we need to add user module to navigation menu. So, lets do that by adding the following code to
resources/views/layouts/app.blade.php in menubar navigation.
<li><a href="{{ url('/users') }}">Users</a></li>
User Listing
Next, when we navigate to
localhost:8000/users
url, you will see an empty page. This is because we have not configured our controller yet. Lets configure our user listing page by creating
users folder under
resources/views folder and inside it create
all.blade.php with following code
@if(session()->has('status')) |
<p class="alert alert-info"> |
{{ session()->get('status') }} |
<div class="panel panel-default"> |
<div class="panel-heading"> |
<a href="{{ route('users.create') }}" class="btn btn-success btn-xs">Add User</a> |
<div class="table-responsive"> |
<table class="table table-bordered"> |
@foreach($users as $user) |
<td>{{ $user->name }}</td> |
<td>{{ $user->email }}</td> |
<td>{{ $user->created_at->format('m-d-Y') }}</td> |
<td>{{ $user->updated_at->format('m-d-Y') }}</td> |
<a href="{{ route('users.edit', $user->id) }}" class="btn btn-success btn-xs">Edit</a> |
<a href="{{ route('users.show', $user->id) }}" class="btn btn-info btn-xs">View</a> |
<form action="{{ route('users.destroy', $user->id) }}" method="POST" style="display:inline-block"> |
{{ method_field('DELETE') }} |
<button class="btn btn-danger btn-xs"> |
<div class="text-center"> |
<p class="alert alert-info"> |
Once our view is ready, lets modify the index function of
UserController.php like the following
* Display a listing of the resource. |
* @return \Illuminate\Http\Response |
$users = User::latest()->paginate(); |
return view('users.all', compact('users')); |
here
latest() function will return user collection with order by updated_at field. However, you can override it by passing the column name like
latest(‘id’). This will return user collection with order by id desc.
Now your
localhost:8000/users
will look like above.
CREATE
Now, let us create an user by clicking on the add user button near user listing. You will see an empty page. Because we have not called necessary view files yet. Lets do that by creating a
create.blade.php file under
resources/views/users and add the following code
@if(session()->has('status')) |
<p class="alert alert-info"> |
{{ session()->get('status') }} |
<div class="col-sm-6 col-sm-offset-3"> |
<div class="panel panel-default"> |
<div class="panel-heading"> |
{{ Form::open(['url' => route('users.store'), 'method' => 'POST' ]) }} |
In above code, we have included
_form.blade.php partial. I have done this, so that we can maintain same form for both create and update. Lets create _form view and fill with following code.
@if (isset($errors) && (count($errors) > 0)) |
<div class="alert alert-danger"> |
@foreach ($errors->all() as $error) |
{{ Form::label('name', 'Name') }} <em>*</em> |
{{ Form::text('name', null, ['class' => 'form-control', 'id' => 'name', 'required' => 'required']) }} |
{{ Form::label('email', 'Email') }} <em>*</em> |
{{ Form::email('email', null, ['class' => 'form-control', 'id' => 'email']) }} |
{{ Form::label('password', 'Password') }} <em>*</em> |
{{ Form::password('password', ['class' => 'form-control', 'id' => 'password']) }} |
{{ Form::submit('Submit', ['class' => 'btn btn-success']) }} |
Now, that we have view file setup, lets modify our create function in UserController.php
* Show the form for creating a new resource. |
* @return \Illuminate\Http\Response |
return view('users.create'); |
Now when you hit localhost:8000/users/create, you should see something like this.
Filling up the form and submitting it will hit
store() function. Lets add validation and logic to save our new user. Also, here I’m going to extract our validation rules and new user creation to new function so that we can avoid code duplication.
private function rules($user = null) { |
'name' => 'required|min:4', |
'email' => 'required|email|unique:users', |
'password' => 'required|min:8' |
$rules['email'] = 'required|email|unique:users,id,'.$user['id']; |
$rules['password'] = 'sometimes|min:8'; |
You can ofcourse use
Form Request Validation for validating form. But for article purpose I have kept it simple.
private function save($request, $user = null) { |
$user->name = $request->input('name'); |
$user->email = $request->input('email'); |
if ($request->has('password')) { |
$user->password = bcrypt($request->input('password')); |
session()->flash('status', 'User '.$status.'d successfully'); |
return redirect(route('users')); |
session()->flash('status', 'Unable to '.$status.' user. Please try again'); |
return back()->withInput(); |
Once user is created, you will see the following.
READ
Now, that we have completed user creation. Lets handle read logic. Since we have used route model binding, for show function in UserController, we will be getting user instance. So we can create
view.blade.php file and pass in the user instance to display user details.
@if(session()->has('status')) |
<p class="alert alert-info"> |
{{ session()->get('status') }} |
<div class="col-sm-6 col-sm-offset-3"> |
<div class="panel panel-default"> |
<div class="panel-heading"> |
<div class="form-horizontal"> |
<label class="col-sm-3 control-label" for="name">Name</label> |
<p class="form-control">{{ $user->name }}</p> |
<label class="col-sm-3 control-label" for="name">Email</label> |
<p class="form-control">{{ $user->email }}</p> |
<label class="col-sm-3 control-label" for="name">Password</label> |
<p class="form-control">********</p> |
<label class="col-sm-3 control-label" for="name">Created On</label> |
<p class="form-control">{{ $user->created_at->format('m-d-Y') }}</p> |
<label class="col-sm-3 control-label" for="name">Last Updated</label> |
<p class="form-control">{{ $user->created_at->format('m-d-Y') }}</p> |
<div class="col-sm-4 col-sm-offset-4"> |
<a href="{{ route('users.index') }}" class="btn btn-success">Back</a> |
view()* Display the specified resource. |
* @return \Illuminate\Http\Response |
public function show($user) |
return view('users.view', compact('user')); |
UPDATE
For update, we need to create
update.blade.php file with the following content
@if(session()->has('status')) |
<p class="alert alert-info"> |
{{ session()->get('status') }} |
<div class="col-sm-6 col-sm-offset-3"> |
<div class="panel panel-default"> |
<div class="panel-heading"> |
{{ Form::model($user, ['url' => route('users.store'), 'method' => 'PUT' ]) }} |
Then modify our
edit() function
* Show the form for editing the specified resource. |
* @return \Illuminate\Http\Response |
public function edit($user) |
return view('users.update', compact('user')); |
Once we submit update form, we will hit update() function. But here, we are going to have same code similar to store() function except we will pass in our user array.
* Update the specified resource in storage. |
* @param \Illuminate\Http\Request $request |
* @return \Illuminate\Http\Response |
public function update(Request $request, $user) |
$this->validate($request, $this->rules($user->id)); |
return $this->save($request, $user); |
After updating, you will see something like this.
DELETE
When user hits delete button, destroy() function will be accessed. So lets modify that.
* Remove the specified resource from storage. |
* @return \Illuminate\Http\Response |
public function destroy($user) |
session()->flash('status', 'User deleted successfully'); |
session()->flash('status', 'Unable to delete user. Please try again'); |
When a user is successfully deleted, you will see this.
That’s it! An easy way to process crud operations in laravel with resource controller and route model binding.