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.
laravel crud resource controller route model binding 1

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.

laravel crud resource controller route model binding 2

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


<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;

class UserController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}

/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}

/**
* 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.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}

/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}

/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}

/**
* Remove the specified resource from storage.
*
* @param int $id
* @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 here

Route 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

@extends('layouts.app')
@section('content')
<div class="container">
@if(session()->has('status'))
<p class="alert alert-info">
{{ session()->get('status') }}
</p>
@endif
<div class="panel panel-default">
<div class="panel-heading">
User Listing
<a href="{{ route('users.create') }}" class="btn btn-success btn-xs">Add User</a>
</div>
<div class="panel-body">
@if (count($users))
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>Username</th>
<th>Email</th>
<th>Created On</th>
<th>Last Updated</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@foreach($users as $user)
<tr>
<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>
<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">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button class="btn btn-danger btn-xs">
<span>DELETE</span>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="text-center">
{{ $users->links() }}
</div>
@else
<p class="alert alert-info">
No Listing Found
</p>
@endif
</div>
</div>
</div>
@endsection
view raw all.blade.php hosted with  by GitHub

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
*/
public function index()
{
$users = User::latest()->paginate();
return view('users.all', compact('users'));
}
view raw index() hosted with  by GitHub

  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.

laravel crud resource controller route model binding 3
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


@extends('layouts.app')
@section('content')
<div class="container">
@if(session()->has('status'))
<p class="alert alert-info">
{{ session()->get('status') }}
</p>
@endif
<div class="col-sm-6 col-sm-offset-3">
<div class="panel panel-default">
<div class="panel-heading">
Add User
</div>
<div class="panel-body">
{{ Form::open(['url' => route('users.store'), 'method' => 'POST' ]) }}
@include('users._form')
{{ Form::close() }}
</div>
</div>
</div>
</div>
@endsection
view raw create.blade.php hosted with  by GitHub

  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">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div class="form-group">
{{ Form::label('name', 'Name') }} <em>*</em>
{{ Form::text('name', null, ['class' => 'form-control', 'id' => 'name', 'required' => 'required']) }}
</div>
<div class="form-group">
{{ Form::label('email', 'Email') }} <em>*</em>
{{ Form::email('email', null, ['class' => 'form-control', 'id' => 'email']) }}
</div>
<div class="form-group">
{{ Form::label('password', 'Password') }} <em>*</em>
{{ Form::password('password', ['class' => 'form-control', 'id' => 'password']) }}
</div>
<div class="form-group">
{{ Form::submit('Submit', ['class' => 'btn btn-success']) }}
</div>
view raw _form.blade.php hosted with  by GitHub

  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
*/
public function create()
{
return view('users.create');
}
view raw create() hosted with  by GitHub

  Now when you hit localhost:8000/users/create, you should see something like this.
laravel crud resource controller route model binding 4
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) {
$rules = [
'name' => 'required|min:4',
'email' => 'required|email|unique:users',
'password' => 'required|min:8'
];
if ($user) {
$rules['email'] = 'required|email|unique:users,id,'.$user['id'];
$rules['password'] = 'sometimes|min:8';
}
return $rules;
}
view raw validation() hosted with  by GitHub

  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) {
$status = "update";
if (! $user) {
$user = new User;
$status = "create";
}
$user->name = $request->input('name');
$user->email = $request->input('email');
if ($request->has('password')) {
$user->password = bcrypt($request->input('password'));
}
if ($user->save()) {
session()->flash('status', 'User '.$status.'d successfully');
return redirect(route('users'));
}
session()->flash('status', 'Unable to '.$status.' user. Please try again');
return back()->withInput();
}
view raw save() hosted with  by GitHub

  Once user is created, you will see the following.

laravel crud resource controller route model binding 5

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.


@extends('layouts.app')
@section('content')
<div class="container">
@if(session()->has('status'))
<p class="alert alert-info">
{{ session()->get('status') }}
</p>
@endif
<div class="col-sm-6 col-sm-offset-3">
<div class="panel panel-default">
<div class="panel-heading">
User Details
</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label" for="name">Name</label>
<div class="col-sm-9">
<p class="form-control">{{ $user->name }}</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" for="name">Email</label>
<div class="col-sm-9">
<p class="form-control">{{ $user->email }}</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" for="name">Password</label>
<div class="col-sm-9">
<p class="form-control">********</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" for="name">Created On</label>
<div class="col-sm-9">
<p class="form-control">{{ $user->created_at->format('m-d-Y') }}</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" for="name">Last Updated</label>
<div class="col-sm-9">
<p class="form-control">{{ $user->created_at->format('m-d-Y') }}</p>
</div>
</div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-4">
<a href="{{ route('users.index') }}" class="btn btn-success">Back</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
view raw view.blade.php hosted with  by GitHub

  view()


/**
* Display the specified resource.
*
* @param App\User $user
* @return \Illuminate\Http\Response
*/
public function show($user)
{
return view('users.view', compact('user'));
}
view raw view() hosted with  by GitHub


Laravel View User
 

UPDATE


For update, we need to create update.blade.php file with the following content


@extends('layouts.app')
@section('content')
<div class="container">
@if(session()->has('status'))
<p class="alert alert-info">
{{ session()->get('status') }}
</p>
@endif
<div class="col-sm-6 col-sm-offset-3">
<div class="panel panel-default">
<div class="panel-heading">
Add User
</div>
<div class="panel-body">
{{ Form::model($user, ['url' => route('users.store'), 'method' => 'PUT' ]) }}
@include('users._form')
{{ Form::close() }}
</div>
</div>
</div>
</div>
@endsection
view raw update.blade.php hosted with  by GitHub


Laravel Edit User  Then modify our edit() function


/**
* Show the form for editing the specified resource.
*
* @param App\User $user
* @return \Illuminate\Http\Response
*/
public function edit($user)
{
return view('users.update', compact('user'));
}
view raw edit() hosted with  by GitHub

  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
* @param App\User $user
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $user)
{
$this->validate($request, $this->rules($user->id));
return $this->save($request, $user);
}
view raw update() hosted with  by GitHub

  After updating, you will see something like this.
Laravel User Updated

DELETE


When user hits delete button, destroy() function will be accessed. So lets modify that.


/**
* Remove the specified resource from storage.
*
* @param App\User $user
* @return \Illuminate\Http\Response
*/
public function destroy($user)
{
if ($user->delete()) {
session()->flash('status', 'User deleted successfully');
} else {
session()->flash('status', 'Unable to delete user. Please try again');
}
return back();
}
  view raw destroy() hosted with  by GitHub

  When a user is successfully deleted, you will see this.
Laravel User Delete

That’s it! An easy way to process crud operations in laravel with resource controller and route model binding.