This tutorial will provide step by step guide on creating Laravel CRUD (Create, Read, Update, Delete) application and here we are going to use Laravel 6 the new LTS version of Laravel Framework.
Read About Laravel 6 New Features – Laravel 6 LTS Is Now officially Released
This tutorial is mostly written for beginner who want to learn and explore laravel 6 framework.
You know starting your new learning journey for any framework the first step you should take is learn and create a practical crud operation, it doest not needs to fancy it just that you should have understanding the basics of it then from there you can move on to the advanced.
Things you should know before diving into Laravel Framework:
- PHP
- MySQL
- HTML & CSS
- Bootstrap 4 (Optional)
- Composer & familiarity with packagist.org
- knowledge of using Git (optional)
Let’s get started by creating brand new laravel 6 application.
Here are the step you needs to follow in order to create laravel crud application.
Table of Contents
Create New Laravel 6 Application
There are two way of create new laravel project first is you can use Laravel CLI or the Composer.
If you have installed laravel CLI already then use following command to create new laravel project
laravel new laravel-crud-app
Or use composer instead
composer create-project --prefer-dist laravel/laravel laravel-crud-app
Here I have used laravel cli:
At end of execution of the above command you see message showing below and your application should be ready to use.
Serving Laravel 6 Application On Localhost
Using Valet
If you are using valet on your development system as I do then open up the terminal and run valet link to generate the symbolic link to your application if not automatically generated.
Use php artisan serve command (HTTP-server)
This is very easy way of serving an laravel application you just need to open terminal if your are on mac or linux or command prompt if your are on widows and use following command to serve your application.
Use this command to run your laravel 6 application.
php artisan serve
As you can see by default the HTTP-server will listen to port 8000 so let’s you want to serve more application then you can also specify port parameter to run your application on specific port.
php artisan serve --port=8181
Database Setup and Configuration
As told you in beginning of this tutorial we are going to use mysql as a backend for our laravel crud application so go ahead and create new database in mysql.
Next open up your newly created laravel application into your favourite code editor, I use Visual Studio code for my programming.
Go ahead and open up .env file and update your date setting like database name username and the password for the database user, as showing below
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel-6-crud-app
DB_USERNAME=root
DB_PASSWORD=
Create Database Migration & Eloquent Model
Next we will need a table into into the database to store the data from our curd app, we can use migration from laravel, which one of the great feature provided by laravel.
Create Migration and Model File
Use below command to create new migration file as well a Model class.
php artisan make:model Post -m
Edit Migration file to add new fileds:
Now go ahead and open up newly created migration file from /database/migrations/ directory and add new fields for the table
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->text('body');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
I have just added two extract fileds here along with id and timestamps because I want to keep this tutorial as simple as possible.
Migrate the Database
We use artisan command to migrate the database, so basically migrating means to create all the table those have been defined inside the migration folder,
As you see laravel 6 by default comes with the default migration files for user, password reset and failed jobs.
Use below command to migrate the database
php artisan migrate
Make post model attributes mass assignable
Laravel Eloquent models protect against mass-assignment by default so to allow our filed to insert into the database we needs to define our model attributes those we want to make mass assignable.
So go ahead and open our newly created model file and make changes according to class showing below:
/app/Post.php
:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = ['name', 'body'];
}
Now our application is all set from the configuration side let’s jump into the CRUD features.
Create resource Controller for Post Model
Laravel controllers are mediator between Model and View laravel controller is responsible for request handling logic, so whatever request is going to come from view the controller is going to handle it, whatever it is for example creating a record, delete a record, update a record or listing records.
So here in order to handle all operations related to our Post module we will create a controller.
Use following command to create new resource controller and don’t forget to pass model option along with the model name, this way we will have entire boiler plate ready for us out of the box
php artisan make:controller PostController --resource --model=Post
After executing this command you should have new file created under /app/app/Http/Controllers/PostController.php
and will have following list of functions ready for us:
<?php
namespace App\Http\Controllers;
use App\Post;
use Illuminate\Http\Request;
class PostController 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 \App\Post $post
* @return \Illuminate\Http\Response
*/
public function show(Post $post)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function edit(Post $post)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Post $post)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function destroy(Post $post)
{
//
}
}
Add Routes:
Routes are basically a http endpoints between our application controller and browser, here we are going to use resource method from the Route class and will provide resource class a second argument.
/routes/web.php
Route::resource('post', 'PostController');
After adding the above route into the web.php file let’s see and test if our reousurce controller and resource route has provided all http requests those we are looking to handle our CRUD operations.
Use following artisan command to list all the routes from the laravel application:
php artisan route:list
We are all set with routes, let’s start am implement our first operation that is Create.
Implement Create Post Feature:
In order to implement create feature first will have to design our application UI as we are starting from scratch so we have nothing yet into the application.
First let’s define our post application layout file so it will have all our master data included in it.
Laravel uses blade template engine to store and compile all laravel views and all laravel views are stored inside /app/resources/views/ folder.
Create master layout file under /app/resources/views/posts/
/app/resources/views/posts/master.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Exclusive Laravel 6 CRUD Application Learning Guide - itechempires.com</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
<link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="jumbotron">
<h1 class="display-6">Exclusive Laravel 6 CRUD Application Demo</h1>
<p class="lead">
Practical laravel 6 application to learn laravel crud application.
</p>
</div>
@yield('body')
</div>
</div>
</div>
</div>
</body>
</html>
If you notice this file here in head section I am using bootstrap stylesheet I have mention in the beginning we are going need bootstrap but it is not compulsory our application is going to work even without bootstrap it is just that bootstrap will provide us better design.
Next create another view file called create.blade.php this file will have create post form along with two input fileds name and body.
/resources/views/posts/create.blade.php
@extends('posts.master')
@section('body')
<div class="card">
<div class="card-header">
<div class="float-right">
<a href="{{ route('post.index') }}" class="btn btn-primary btn-sm">Back to Posts</a>
</div>
Create Post
</div>
<div class="card-body">
@if ($errors->any())
<div class="alert alert-danger">
<p>
<strong>Input Error!</strong>
</p>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="POST" action="{{ route('post.store') }}">
@csrf
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" name="name" value="{{ old('name') }}">
</div>
<div class="form-group">
<label for="body">Body</label>
<textarea class="form-control" id="body" name="body" rows="5">{{ old('body') }}</textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
@endsection
Handle request logic inside Post Controller to have create form listed and handle post request coming from the above form.
So open up PostController.php file and change following two methods create and store.
/app/app/Http/Controllers/PostController.php
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('posts.create');
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required',
'body' => 'required|min:10'
]);
Post::create($request->only(['name', 'body']));
return redirect()->route('post.index')->with('success', 'Post created successfully.');
}
Our create feature is ready, in next step let’s implement Read feature.
Implement Read Post Feature:
In this step we are going to list all the records from posts table alright so in order to do that we again needs to work on controller as well as view.
Okay so go ahead and create new blade template file under views folder call it index.blade.php
/resources/views/posts/index.blade.php
:
@extends('posts.master') @section('body')
<div class="card">
<div class="card-header">
<div class="float-right">
<a href="{{ route('post.create') }}" class="btn btn-primary btn-sm"
>Add</a
>
</div>
Posts
</div>
<div class="card-body">
@if ($message = Session::get('success'))
<div class="alert alert-success">
<p>{{ $message }}</p>
</div>
@endif
<table class="table table-bordered">
<thead>
<tr>
<th>No</th>
<th>Name</th>
</tr>
</thead>
@foreach ($posts as $key => $post)
<tbody>
<tr>
<td>
{{ $key + 1 }}
</td>
<td>
<a href="{{ route('post.show',$post->id) }}">
{{ $post->name }}
</a>
</td>
</tr>
</tbody>
@endforeach
</table>
{!! $posts->links() !!}
</div>
@endsection
</div>
If you loot at this file carefully you will notice that we are rendering posts from $posts variable using foreach simply listing it using the html table.
So in order to have $posts variable accessible into the index.balade.php file, we will have to add controller logic into our Post Controller’s index function.
Why index method and not other? because if you look at the route listing for the GET request of the post route is using index() function from PostController.
Okay let’s open PostController.php class and change index function as showing below:
/app/Http/Controllers/PostController.php
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$posts = Post::latest()->paginate(10);
return view('posts.index', compact('posts'));
}
Now our listing should work and also create post feature will work without any errors.
Implement Update Post Feature
Next let’s look at the update action this is also called as edit action, basically we are going to edit our existing post.
So we are going to need three things here first is the edit form which is going to show us an exiting recored details with the update button, second is the controller function to handle update request and the third thing is link to the update view.
First let’s create a link for the edit page route, in order to do that will have to add link from the post listing, so let’s update our index.blade.php file to have new column for listing table.
/resources/views/posts/index.blade.php
@extends('posts.master') @section('body')
<div class="card">
<div class="card-header">
<div class="float-right">
<a href="{{ route('post.create') }}" class="btn btn-primary btn-sm"
>Add</a
>
</div>
Posts
</div>
<div class="card-body">
@if ($message = Session::get('success'))
<div class="alert alert-success">
<p>{{ $message }}</p>
</div>
@endif
<table class="table table-bordered">
<thead>
<tr>
<th>No</th>
<th>Name</th>
<th>Action</th>
</tr>
</thead>
@foreach ($posts as $key => $post)
<tbody>
<tr>
<td>
{{ $key + 1 }}
</td>
<td>
<a href="{{ route('post.show',$post->id) }}">
{{ $post->name }}
</a>
</td>
<td>
<a
class="btn btn-primary btn-sm"
href="{{ route('post.edit',$post->id) }}"
>Edit</a>
</td>
</tr>
</tbody>
@endforeach
</table>
{!! $posts->links() !!}
</div>
@endsection
</div>
Create new blade template file to create update post form.
/resources/views/posts/edit.blade.php
@extends('posts.master')
@section('body')
<div class="card">
<div class="card-header">
<div class="float-right">
<a href="{{ route('post.index') }}" class="btn btn-primary btn-sm">Back to Posts</a>
</div>
Update Post
</div>
<div class="card-body">
@if ($errors->any())
<div class="alert alert-danger">
<p>
<strong>Input Error!</strong>
</p>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('post.update',$post->id) }}" method="POST">
@csrf @method('PUT')
<div class="form-group">
<label for="name">Name</label>
<input
type="text"
class="form-control"
id="name"
name="name"
value="{{ $post->name }}"
/>
</div>
<div class="form-group">
<label for="body">Body</label>
<textarea
class="form-control"
id="body"
name="body"
rows="5"
>{{ $post->body }}</textarea
>
</div>
<button type="submit" class="btn btn-primary">Update</button>
</form>
</div>
@endsection
Make sure to check the above form and you will see in the form action we have POST method but by using @csrf @method('PUT')
we are putting in and hidden filed with the value PUT and as the end result it will generate the filed like this `<input type=”hidden” name=”_method” value=”PUT”>`
Next lets update our controller functions first is for viewing post and second is updating post and those functions called edit()
and update()
/app/Http/Controllers/PostController.php
/**
* Show the form for editing the specified resource.
*
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function edit(Post $post)
{
return view('posts.edit', compact('post'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Post $post)
{
$request->validate([
'name' => 'required',
'body' => 'required|min:10',
]);
$post->update($request->only(['name', 'body']));
return redirect()->route('post.index')->with('success', 'Post has been updated successfully!');
}
We are done we have added our update feature successfully, you can ahead and test updating feature on your end like showing below:
- Open any post to edit and make some changes
2. After making changes click submit you see the post has updated along with the success message.
Implement Delete Post Feature
Now let’s implement last operation from laravel crud which is delete action, so to implement delete action will have two make changes at two places first is we needs to have a delete button on post listing and second thing is yes our controller class
will have to add logic to the destroy()
function.
Open index.blade.php file and add new button to the action column, this is not going to be simple button it is going to be submit button with the inline form:
/resources/views/posts/index.blade.php
<form
action="{{ route('post.destroy',$post->id) }}"
method="POST"
style="display: inline;"
>
@csrf @method('DELETE')
<button type="submit" class="btn btn-danger btn-sm">
Delete
</button>
As you can see are using next laravel custom action method here that id DELETE
Next change destroy()
function to have delete logic
/app/Http/Controllers/PostController.php
/**
* Remove the specified resource from storage.
*
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('post.index')->with('success', 'Post has been deleted successfully!');
}
Implement View Post Feature
This last but not the list action if you notice the index.blade.php
file I have added an anchor tag inside the name column:
<a href="{{ route('post.show',$post->id) }}">{{ $post->name }}</a>
This action is just for viewing a complete post so to have this view action we needs to update our post controller and will need new view let’s add real quick.
change show() function from post controller:
/app/Http/Controllers/PostController.php
/**
* Display the specified resource.
*
* @param \App\Post $post
* @return \Illuminate\Http\Response
*/
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
Add new blade template file under views folder
/resources/views/posts/show.blade.php
@extends('posts.master')
@section('body')
<div class="card">
<div class="card-header">
<div class="float-right">
<a href="{{ route('post.index') }}" class="btn btn-primary btn-sm">Back to Posts</a>
</div>
Post
</div>
<div class="card-body">
<h2>{{ $post->name }}</h2>
<p>
{{ $post->body }}
</p>
</div>
@endsection
Now you can go ahead and click the post name from the listing you should be redirected to the post view page.
Conclusion:
I know it is long boarding tutorial but kind of helpful for beginner to start learning laravel framework, while learning being a developer practical is most important thing.
If you follow this tutorial very carefully then you will have clear understanding of routes, controllers, models, view and laravel validations
I have tried to cover each and every concept in detail which I have used in this tutorial, still if you have any question or queries let me know in comment section below.
Easy to understand. Thank you very much. Want to more advance tutorial.