Laravel 8 has released on September 8th, 2020 with the new amazing features. Every time, Laravel improves the features, security patches from it’s previous version. Laravel 8 introduces the features like Jetstream, model factory classes, migration squashing, job batching, improved rate limiting, queue improvements, dynamic Blade components, Tailwind pagination views, time testing helpers, and many more. We will see all these features in this Laravel 8 tutorial series. At very first, we will be starting with Laravel 8 CRUD application tutorial. So, let’s create a new Laravel 8 project.
Prerequisites
For creating a Laravel 8 project, I will be using the composer. So, I have already installed it in my system. Laravel 8 requires the PHP >= 7.3 version. Also, it requires the following extensions enabled in PHP ini file.
- PHP >= 7.3
- BCMath PHP Extension
- Ctype PHP Extension
- Fileinfo PHP extension
- JSON PHP Extension
- Mbstring PHP Extension
- OpenSSL PHP Extension
- PDO PHP Extension
- Tokenizer PHP Extension
- XML PHP Extension
For the Laravel 8 CRUD application, you will require the following tools-
- PHP >= 7.3
- MySQL (version > 5)
- Apache/Nginx Server
- VS Code Editor
Create a Laravel 8 CRUD Application Project
For creating the Laravel 8 application, we will be using the composer. You can use command prompt or terminal for hitting the below command.
$ composer create-project --prefer-dist laravel/laravel laravel-8-crud
It will start creating a Laravel 8 project. Inside the project folder, it will add the required dependencies. So, just wait while it completes the installation.
When the project is ready, let’s create a database in MySQL.
How to Send Email Using Mailgun in Laravel 8
Create and Configure Database For Laravel 8 CRUD
For the database, I will be using the MySQL. Hence, create a new database by hitting the below command.
CREATE DATABASE laravel8_crud;
When the database is ready, let’s configure it for the Laravel 8 project. For the database configuration, navigate to the .env file and replace the credentials as showing below.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel8_crud
DB_USERNAME=root
DB_PASSWORD=root
Now, we have connected the database with the Laravel 8 project. In the next step, we will check whether the connection has established or not.
Create a Model and Migration in Laravel 8
In this CRUD application, I will work on the Article for applying the CRUD operations. So, I will create a model and migration for the Article.
php artisan make:model Article --migration
The above command will create a model and the migration file for the Article.
When the model has been created, you will see the new feature of the Laravel 8 inside the folder structure. This time you will find a separate folder for the Models. And every model will be placing inside this Models folder. So, this is very interesting.
The migration file for the article has been added inside the database/migrations folder as well.
So, in the create_articles_table migration, we will add some fields.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateArticlesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->string("title");
$table->string("description");
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('articles');
}
}
Now, we have the schema for the articles table. Therefore, let’s migrate it inside the database.
php artisan migrate
The above command will generate the tables for the specified migrations in the database.
Once the tables has been created. Now, let’s add the fillable data in the article model.
Laravel 7 Upload Multiple Images with Image Validation
Add Mass Assignment For the Article Model
When you will open the model (Article.php), you will find a new namespace named Factory that is model factory class. This one is the second feature of the Laravel 8. We will discuss it in the upcoming tutorials.
Now, we will be adding the fillable data here. The only fillable data will be created and updated during the CRUD operation.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use HasFactory;
protected $fillable = [
"title", "description"
];
}
I have passed the fillable data in the Array. Now, let’s create a controller for the Article.
How to Send Email in Laravel 8 Using Gmail SMTP
Create a Controller For the Article
For the entire CRUD operations, we will require a Controller to operate all the functionalities. The Laravel provides the resource with the controller. The resource provides the default CRUD methods inside the controller.
php artisan make:controller ArticleController --resource
When the controller has been created, you will find the following methods inside it.
- index()
- create()
- store()
- show()
- edit()
- update()
- destory()
These methods will be used in the entire CRUD operations. Hence, add the below snippet in the ArticleController.php file.
<?php
namespace App\Http\Controllers;
use App\Models\Article;
use Illuminate\Http\Request;
class ArticleController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$articles = Article::latest()->paginate(5);
return view("index", compact('articles'));
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('create-article');
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$request->validate(
[
"title" => "required",
"description" => "required"
]
);
$article = Article::create($request->all());
if(!is_null($article)) {
return back()->with("success", "Success! Article created");
}
else {
return back()->with("failed", "Alert! Article not created");
}
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show(Article $article)
{
return view('show-article', compact('article'));
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit(Article $article)
{
return view('edit-article', compact('article'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Article $article)
{
$request->validate([
"title" => "required",
"description" => "required",
]);
$article = $article->update($request->all());
if(!is_null($article)) {
return back()->with("success", "Success! Article updated");
}
else {
return back()->with("failed", "Alert! Article not updated");
}
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Article $article)
{
$article = $article->delete();
if(!is_null($article)) {
return back()->with("success", "Success! Article deleted");
}
else {
return back()->with("failed", "Alert! Article not deleted");
}
}
}
Create Auth Using Jetstream and Intertia js in Laravel 8
Add Route For Laravel 8 CRUD Application
Now, for the ArticleController’s functions, we will have to create a resource route. The route will be the type of web. So, add the route in the web.php file.
<?php
use App\Http\Controllers\ArticleController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::resource('articles', ArticleController::class);
In the above route, you will notice that I have added the controller class. When you will specify the controller class, it will imported the class name as a namespace.
Create Views For the Laravel 8 CRUD Application
We will require the following views for handling the CRUD operations.
- master.blade.php
- index.blade.php
- create-article.blade.php
- show-article.blade.php
- edit-article.blade.php
In the master.blade.php file, I will be putting out the Bootstrap. So, that we can extend this layout in all the blade file.
<!doctype html>
<html lang="en">
<head>
<title> Laravel 8 CRUD - @yield('title') - Programming Fields</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://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 mt-5">
@yield('content')
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
Once, the master layout has been created, we can extend it for the further implementation. In the index.blade.php file, we will list out the articles. Also, we will create a navigation for creating a new article.
@extends("master")
@section("title") Articles @endsection
@section("content")
<div class="row mb-4">
<div class="col-xl-6">
@if(Session::has('success'))
<div class="alert alert-success alert-dismissible">
<button type="button" class="close" data-dismiss="alert">× </button>
{{Session::get('success')}}
</div>
@else
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert">× </button>
{{Session::get('failed')}}
</div>
@endif
</div>
<div class="col-xl-6 text-right">
<a href="{{route('articles.create')}}" class="btn btn-success "> Add New </a>
</div>
</div>
<table class="table table-striped">
<thead>
<th> Id </th>
<th> Title </th>
<th> Description </th>
<th> Action </th>
</thead>
<tbody>
@if(count($articles) > 0)
@foreach($articles as $article)
<tr>
<td> {{$article->id}} </td>
<td> {{$article->title}} </td>
<td> {{$article->description}} </td>
<td>
<form action="{{route('articles.destroy', $article->id)}}" method="POST">
@csrf
@method('DELETE')
<a href="{{route('articles.show', $article->id)}}" class="btn btn-sm btn-info"> View </a>
<a href="{{route('articles.edit', $article->id)}}" class="btn btn-sm btn-success"> Edit </a>
<button type="submit" class="btn btn-sm btn-danger"> Delete </button>
</form>
</td>
</tr>
@endforeach
@endif
</tbody>
</table>
{!! $articles->links() !!}
@endsection
When you will click on Add New button, it will redirect you to create-article.blade.php file.
@extends("master")
@section("title") Create Article @endsection
@section("content")
<div class="container">
<div class="row">
<div class="col-xl-12 col-lg-12 text-right">
<a href="{{route('articles.index')}}" class="btn btn-danger"> Back to Articles </a>
</div>
</div>
<div class="row">
<div class="col-xl-6 col-lg-6 col-md-6 col-sm-12 col-12 m-auto">
<form action="{{route('articles.store')}}" method="POST">
@csrf
<div class="card shadow">
@if(Session::has('success'))
<div class="alert alert-success alert-dismissible">
<button type="button" class="close" data-dismiss="alert">× </button>
{{Session::get('success')}}
</div>
@elseif(Session::has('failed'))
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert">× </button>
{{Session::get('failed')}}
</div>
@endif
<div class="card-header">
<h4 class="card-title"> Create Article </h4>
</div>
<div class="card-body">
<div class="form-group">
<label for="title"> Title </label>
<input type="text" name="title" class="form-control" id="title" value="{{old('title')}}">
{!!$errors->first("title", "<span class='text-danger'>:message </span>")!!}
</div>
<div class="form-group">
<label for="description"> Description </label>
<textarea class="form-control" name="description" id="description">{{old('description')}}</textarea>
{!!$errors->first("description", "<span class='text-danger'>:message </span>") !!}
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-success"> Save </button>
</div>
</div>
</form>
</div>
</div>
</div>
@endsection
When you will save the article, you will have the option to View, Edit and Delete for the article.
@extends("master")
@section("title") Show Article @endsection
@section("content")
<div class="container">
<div class="row">
<div class="col-xl-12 col-lg-12 text-right">
<a href="{{route('articles.index')}}" class="btn btn-danger"> Back to Articles </a>
</div>
</div>
<div class="row">
<div class="col-xl-6 col-lg-6 col-md-6 col-sm-12 col-12 m-auto">
<div class="card shadow">
<div class="card-header">
<h4 class="card-title"> Show Article </h4>
</div>
<div class="card-body">
<div class="form-group">
<label for="title"> Title </label>
<input type="text" readonly name="title" class="form-control" id="title" value="@if(!empty($article)) {{$article->title}} @endif">
</div>
<div class="form-group">
<label for="description"> Description </label>
<textarea class="form-control" readonly name="description" id="description">@if(!empty($article)) {{$article->description}} @endif</textarea>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
In the show-article.blade.php file, the selected article will be displaying. Also, you won’t have the option to edit because the input fields are set to readonly.
@extends("master")
@section("title") Update Article @endsection
@section("content")
<div class="container">
<div class="row">
<div class="col-xl-12 col-lg-12 text-right">
<a href="{{route('articles.index')}}" class="btn btn-danger"> Back to Articles </a>
</div>
</div>
<div class="row">
<div class="col-xl-6 col-lg-6 col-md-6 col-sm-12 col-12 m-auto">
<form action="{{route('articles.update', $article->id)}}" method="POST">
@csrf
@method('PUT')
<div class="card shadow">
@if(Session::has('success'))
<div class="alert alert-success alert-dismissible">
<button type="button" class="close" data-dismiss="alert">× </button>
{{Session::get('success')}}
</div>
@elseif(Session::has('failed'))
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert">× </button>
{{Session::get('failed')}}
</div>
@endif
<div class="card-header">
<h4 class="card-title"> Update Article </h4>
</div>
<div class="card-body">
<div class="form-group">
<label for="title"> Title </label>
<input type="text" name="title" class="form-control" id="title" value="@if(!empty($article)) {{$article->title}} @endif">
{!!$errors->first("title", "<span class='text-danger'>:message </span>")!!}
</div>
<div class="form-group">
<label for="description"> Description </label>
<textarea class="form-control" name="description" id="description">@if(!empty($article)){{$article->description}}@endif</textarea>
{!!$errors->first("description", "<span class='text-danger'>:message </span>") !!}
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-success"> Update </button>
</div>
</div>
</form>
</div>
</div>
</div>
@endsection
In the update-article.blade.php file, you can update the article as per the article id.
Laravel 7 Yajra DataTable with Server Side Processing
Laravel 8 CRUD Application Result
It’s time to test the application and see the result. So, save and run the project and follow the below guide.
For creating the article, if you leave form fields to blank, it will show you the validation error message.
But, when you will fill up the input fields, it will return a success message.
When, article is created, you can redirect back to the article lists. In which, you will have the below screen with the article lists.
When you will click on the View, you will have the article detail like below.
To edit the article, you can click on the Edit button.
When you will change the value and click on the Update button, the article will be updated.
When you will delete the article, you will have the success response like showing below.
Conclusion
Finally, we have completed the Laravel 8 CRUD Application tutorial. I hope this tutorial will help as a basic guide for the beginners. If you are a newbie in Laravel, and have any doubt or query regarding the post then please let me know in the comment section. I will try my best to reach out to you with the solution. So, stay connected and enjoy coding.
Ananya Raut says
Thank You so much for sharing laravel 8 crud application post.
Peter Morgan-Tansley says
Hi
I can’t seem to get this working! I have followed all the instructions and then run php artisan serve but I just get a 404 error.
What am I doing wrong?
Umesh Rana says
Have you created the Route properly? It seems you have not created the required routes that’s why it is showing 404 error.