Laravel 9 CRUD Operation From Scratch Step By Step Guideline

  • 04-08-2022
  • 749
  • Laravel 9
  • Haresh Chauhan

Laravel 9 CRUD operation from the scratch step-by-step guideline. In this tutorial, we will create a CRUD operation using laravel 9 with the help of POST example with validation at store time and using resource controller and routes.

Throughout this laravel 9 full CRUD operation from scratch with an example for beginners tutorial, You will learn step by step guide on how to create crud operation in laravel 9 and how to validate the field on store & update form data to the database post table in this best laravel CRUD operation with bootstrap help.

In this crud operation from step one, we will create a new fresh laravel project and implement POST crud operation in this laravel 9 application. We will create a post-crud operation in this laravel 9 application. At the end of this tutorial you will learn How to create, ready, store, edit, update, show, and delete from the database in the laravel 9 application.

CRUD REVIEW :

Step 1: Create Project

Firstly, We will create fresh new a laravel project using the below command. Please copy the below command and paste it into your terminal. This command will clone fresh new laravel latest project in your system. Once hit the command it will start cloning just wait for some time it will install composer also.

Once you create a project using the suggested command, go to the project directory in your terminal using "cd {project name}".

composer create-project laravel/laravel laravel9

cd laravel9

Step 2: Database Config

On the project root directory, you will see a .env file. just open in your editor and config your database. Goto your PHPMyAdmin and create a database. Given that the database name here and the default user will be root and enter the password your set in your database.

.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=

Step 3: Create Migration & Model

To create Model, Migration, and resource controller together hit below the suggested command. This will create that's there's together.

php artisan make:model Post -mc --resource

Taking the example of a post, Here I will create a full CRUD operation for the post. Create a migration with the field that you want to add to your post table.

database/migrations/2022_08_03_093328_create_posts_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePostsTable extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('description');
            $table->enum('status',['active','inactive']);
            $table->timestamps();
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
 }

Migrate table using below command. This command will migrate all the tables in your database. Use the below command, Hit in your project command line tool.

php artisan migrate

Firstly add the fillable property as an array with protection in the model at the top, Add all the column names which you added in the migration post table. Define all methods for full crud operation.

postCreate method for the create post, postUpdate method for the update our post which we created, postGet method for the listing of your post, postFind method for the find full details of the post with the description through the unique id from the table, postDelete method for the deleted post from the database.

app/Models/Post.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Arr;

class Post extends Model
{
    use HasFactory;

    protected $fillable = [
        'title',
        'description',
        'status'
    ];

    public function postCreate($input)
    {
        return static::create(Arr::only($input,$this->fillable));
    }

    public function postUpdate($id,$input)
    {
        return static::where('id',$id)->update(Arr::only($input,$this->fillable));
    }

    public function postGet($request)
    {
        return static::select(
            'id',
            'title',
            'description',
            'status'
        )
        ->paginate(10);
    }

    public function postFind($id)
    {
        return static::find($id);
    }

    public function postDelete($id)
    {
        return static::destroy($id);
    }
}  

We created a resource controller so all that CRUD methods by default will be available.

Post model defines as a public variable in the __construct method. Index method will fetch post list from the database post table, Create a method for the view create form, store method will store post data in the post table from the client side form request with post method it will also check validation, Show method for the read specific post from the list, Edit method for the update your post which your created earlier, and Update method for the update edited post content in the database through the unique, Destroy method for the deleted post from the database post table.

app/Http/Controllers/PostController.php
<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public $post;

    public function __construct()
    {
        $this->post = new Post;
    }
    /**
      * Display a listing of the resource.
      *
      * @return \Illuminate\Http\Response
      */
    public function index()
    {
        $posts = $this->post->postGet();

        return view('post',compact('posts'));
    }

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

    /**
      * Store a newly created resource in storage.
      *
      * @param  \Illuminate\Http\Request  $request
      * @return \Illuminate\Http\Response
      */
    public function store(Request $request)
    {
        $validator = $this->validate($request,[
            'title' => 'required|max:255|unique:posts',
            'description' => 'required',
            'status' => 'required|in:active,inactive'
        ]);

        $this->post->postCreate($validator);

        return redirect()->route('post.index')->with('success','Post created successfully');
    }

    /**
      * Display the specified resource.
      *
      * @param  \App\Models\Post  $post
      * @return \Illuminate\Http\Response
      */
    public function show($id)
    {
        $post = $this->post->postFind($id);

        return view('post-show',compact('post'));
    }

    /**
      * Show the form for editing the specified resource.
      *
      * @param  \App\Models\Post  $post
      * @return \Illuminate\Http\Response
      */
    public function edit($id)
    {
        $post = $this->post->postFind($id);

        return view('post-edit',compact('post'));
    }

    /**
      * Update the specified resource in storage.
      *
      * @param  \Illuminate\Http\Request  $request
      * @param  \App\Models\Post  $post
      * @return \Illuminate\Http\Response
      */
    public function update(Request $request,$id)
    {
        $validator = $this->validate($request,[
            'title' => 'required|max:255|unique:posts,title,'.$id,
            'description' => 'required',
            'status' => 'required|in:active,inactive'
        ]);

        $this->post->postUpdate($id,$validator);

        return redirect()->route('post.index')->with('success','Post updated successfully');
    }

    /**
      * Remove the specified resource from storage.
      *
      * @param  \App\Models\Post  $post
      * @return \Illuminate\Http\Response
      */
    public function destroy($id)
    {
        $this->post->postDelete($id);

        return redirect()->route('post.index')->with('success','Post deleted successfully');
    }
}

Step 4: Routes

Create routes for the post CRUD operation in your web.php file which is stored in the routes folder from the root. Here you can also use Route resource for the best practice. Here I define the easy controller method route for a better understanding.

Import your Post Controller in the web.php file at the top below the route use. Create full post CRUD operation routes. Also, give a name to each route in case future you need to change your route URL you can easy to change it without any issues raise.

routes/web.php
<?php

use Illuminate\Support\Facades\Route;

use App\Http\Controllers\PostController;

/*
|--------------------------------------------------------------------------
| 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::get('post',[PostController::class,'index'])->name('post.index');
Route::get('post/create',[PostController::class,'create'])->name('post.create');
Route::post('post/store',[PostController::class,'store'])->name('post.store');
Route::get('post/show/{id}',[PostController::class,'show'])->name('post.show');
Route::get('post/edit/{id}',[PostController::class,'edit'])->name('post.edit');
Route::patch('post/update/{id}',[PostController::class,'update'])->name('post.update');
Route::get('post/destroy/{id}',[PostController::class,'destroy'])->name('post.destroy');

Step 5: Blade Files

Blade file for the post listing, take the help of bootstrap for the better-defined structure of the table listing post.

Compacted posts variable in the index method from the controller will receive post list from the database. Also given pagination to each ten pages will available next page from eleven.

resources/views/post.blade.php
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>Post List - Webappfix</title>
  </head>
  <body>
    <div class="container mt-5">
      @if (\Session::has('success'))
        <div class="alert alert-success">{{ \Session::get('success') }}</div>
      @endif
      <a class="btn btn-success" href="{{ route('post.create') }}">Create</a>
      <table class="table">
        <thead>
          <tr>
            <th scope="col">ID</th>
            <th scope="col">Title</th>
            <th scope="col">Status</th>
            <th scope="col">View</th>
            <th scope="col">Edit</th>
            <th scope="col">Delete</th>
          </tr>
        </thead>
        <tbody>
          @foreach ($posts as $post)
            <tr>
              <th scope="row">{{ $post->id }}</th>
              <td>{{ $post->title }}</td>
              <td>{{ $post->status }}</td>
              <td><a class="btn btn-primary" href="{{ route('post.show',$post->id) }}">View</a></td>
              <td><a class="btn btn-info text-white" href="{{ route('post.edit',$post->id) }}">Edit</a></td>
              <td><a class="btn btn-danger" href="{{ route('post.destroy',$post->id) }}">Delete</a></td>
            </tr>
          @endforeach
        </tbody>
      </table>
      {{-- PAGINATION --}}
      <div class="text-right paginate">
        {{ $posts->links('pagination::bootstrap-4') }}
      </div>
    </div>
    <!-- Bootstrap Script -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
  </body>
</html>

Blade file for the create post form, Create a form for the post create. Also defined validation and form method and action all things.

resources/views/post-create.blade.php
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>Post Create - Webappfix</title>
  </head>
  <body>
    <div class="container mt-5">
      <form action="{{ route('post.store') }}" method="post">
        @csrf
        <div class="form-group">
          <label for="title">Title</label>
          <input type="text" name="title" class="form-control" id="title" placeholder="Title" value="{{ old('title') }}">
          @error('title') <font color="red">{{ $message }}</font>@endError
        </div>
        <br>
        <div class="form-group">
          <label for="description">Description</label>
          <textarea class="form-control" id="description" name="description" cols="30" rows="10">{{ old('description') }}</textarea>
          @error('description') <font color="red">{{ $message }}</font>@endError
        </div>
        <br>
        <div class="form-group">
          <label for="status">Status</label>
          <select class="form-control" name="status" id="status">
            <option value="active">Active</option>
            <option value="inactive">InActive</option>
          </select>
        </div>
        <br>
        <div class="form-group mt-2">
          <button type="submit" class="btn btn-info text-white">Save Post</button>
        </div>
      </form>
    </div>
    <!-- Bootstrap Script -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
  </body>
</html>

For the show individual with the full description. Create a show blade file and read the full post article.

resources/views/post-show.blade.php
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>Post Show - Webappfix</title>
  </head>
  <body>
    <div class="container mt-5">
      <a class="btn btn-success" href="{{ route('post.index') }}">List</a>
      <form action="#">
        <div class="form-group">
          <label for="title">Title</label>
          <input type="text" name="title" class="form-control" id="title" placeholder="Title" value="{{ $post->title }}" readonly>
          @error('title') <font color="red">{{ $message }}</font>@endError
        </div>
        <br>
        <div class="form-group">
          <label for="description">Description</label>
          <textarea class="form-control" id="description" name="description" cols="30" rows="10" readonly>{{ $post->description }}</textarea>
          @error('description') <font color="red">{{ $message }}</font>@endError
        </div>
        <br>
        <div class="form-group">
          <label for="status">Status</label>
          <select class="form-control" name="status" id="status" readonly>
            <option {{ $post->status == 'active' ? 'selected' : '' }} value="active">Active</option>
            <option {{ $post->status == 'inactive' ? 'selected' : '' }} value="inactive">InActive</option>
          </select>
        </div>
        <br>
      </form>
    </div>
    <!-- Bootstrap Script -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
  </body>
</html>

Post edit blade file for the edit and update post which we create before in case any word is missed. The same form which we used in post create just changed form method and pre-filled value from the database post table.

resources/views/post-edit.blade.php
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>Post Edit - Webappfix</title>
  </head>
  <body>
    <div class="container mt-5">
      <form action="{{ route('post.update',$post->id) }}" method="post">
        @method('PATCH')
        @csrf
        <div class="form-group">
          <label for="title">Title</label>
          <input type="text" name="title" class="form-control" id="title" placeholder="Title" value="{{ $post->title }}">
          @error('title') <font color="red">{{ $message }}</font>@endError
        </div>
        <br>
        <div class="form-group">
          <label for="description">Description</label>
          <textarea class="form-control" id="description" name="description" cols="30" rows="10">{{ $post->description }}</textarea>
          @error('description') <font color="red">{{ $message }}</font>@endError
        </div>
        <br>
        <div class="form-group">
          <label for="status">Status</label>
          <select class="form-control" name="status" id="status">
            <option {{ $post->status == 'active' ? 'selected' : '' }} value="active">Active</option>
            <option {{ $post->status == 'inactive' ? 'selected' : '' }} value="inactive">InActive</option>
          </select>
        </div>
        <br>
        <div class="form-group mt-2">
          <button type="submit" class="btn btn-info text-white">Save Post</button>
        </div>
      </form>
    </div>
    <!-- Bootstrap Script -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
  </body>
</html>

Step 6: Start Development Server

Hit below the suggested command in your project terminal. Command will start the development server in your system. There you will see a local host IP address copy it and paste in your web browser.

php artisan server

Create a post by entering the below URL in your web browser.

Middleware Example With Authentication Laravel 9

  http://127.0.0.1:8000/post

Laravel 9 Create Custom Auth Guard Multi Login Authentication System Tutorial

CONCLUSION

Laravel 9 full CRUD operation is discussed in this post step by step, each step of this operation is mandatory. This is very simple to learn there is no difficulty you will face. Definity this post will help you to create a CRUD operation. Also, I have given source code and example if you getting any difficulty just download and run in the system.


We always thanks to you for reading our blogs.


dharmesh-image

Dharmesh Chauhan

(Swapinfoway Founder)

Hello Sir, We are brothers origin from Gujarat India, Fullstack developers working together since 2016. We have lots of skills in web development in different technologies here I mention PHP, Laravel, Javascript, Vuejs, Ajax, API, Payment Gateway Integration, Database, HTML5, CSS3, and Server Administration. So you need our service Please Contact Us

haresh-image

Haresh Chauhan

(Co-Founder)


We Are Also Recommending You :