CRUD (Create Read Update Delete) in a Laravel 7

CRUD stands for Create, Read, Update, and Delete. This needs when working with the database data.

With this operation, a user can perform its action, and the changes will be saved in the database.

In this tutorial, I show how you can select, insert, update, and delete a record from the MySQL database with Laravel 7.

CRUD (Create Read Update Delete) in a Laravel 7


Contents

  1. Create a Table
  2. Model
  3. Route
  4. Controller
  5. View
  6. Output
  7. Conclusion

1. Create a Table

  • Create a table subjects using migration.
php artisan make:migration create_subjects_table
  • Now, navigate to database/migrations/ folder from the project root.
  • Find a PHP file that ends with create_subjects_table and open it.
  • Define the table structure in the up() method.
public function up()
{
    Schema::create('subjects', function (Blueprint $table) {
       $table->id();
       $table->string('name');
       $table->text('description');
       $table->timestamps();
    });
}
  • Run the migration –
php artisan migrate

2. Model

  • Create Subjects Model.
php artisan make:model Subjects
  • Specify mass assignable Model attributes – name, and description using the $fillable property.

Completed Code

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Subjects extends Model
{

   protected $fillable = [
      'name','description' 
   ];

}

3. Route

  • Open routes/web.php file.
  • Define 6 routes –
    • /subjects – Display subject list.
    • /subjects/create – Open add subject view.
    • /subjects/store – Submit subject form to insert a record.
    • /subjects/store/{id} – Open edit subject view by id.
    • /subjects/update/{id} – Submit edit form to update a record by id.
    • /subjects/delete/{id} – Delete a subject by id.
## View 
Route::get('/subjects', 'SubjectsController@index')->name('subjects');

## Create
Route::get('/subjects/create', 'SubjectsController@create')->name('subjects.create');
Route::post('/subjects/store', 'SubjectsController@store')->name('subjects.store');

## Update
Route::get('/subjects/store/{id}', 'SubjectsController@edit')->name('subjects.edit');
Route::post('/subjects/update/{id}', 'SubjectsController@update')->name('subjects.update');

## Delete
Route::get('/subjects/delete/{id}', 'SubjectsController@destroy')->name('subjects.delete');

4. Controller

  • Create SubjectsController Controller.
php artisan make:controller SubjectsController
  • Open app/Http/Controllers/SubjectsController.php file.
  • I am using Session flash to display insert, update, and delete response on the page.
  • Import Subjects Model.
  • Create 6 methods –
    • index() – Select all records from the subjects table and assign in $subjects. Load subjects.index view and pass $subjects.
    • create() – With this method load subjects.create view for adding a new subject.
    • store() – With this method insert a new record in the subjects table.

Insert a record if values are validated. If values are not validated then return to the create view with the error response.

If a record is successfully inserted then store success message in Session::flash('message') and class name in Session::flash('alert-class') and return to the subjects route.

Similarly, if a record is not inserted then store the failed message in Session::flash('message') and class name in Session::flash('alert-class').

    • edit() – With this method load edit subject view. Select a record from the subjects table by $id and assign in $subject. Load subjects.edit view and pass $subject.
    • update() – With this method update a record in the subjects table.

If values are not validated then redirect to edit view with the error response. Select a record from the subjects table by $id and assign in $subject.

If a record is successfully updated then store the success message in Session::flash('message') and class name in Session::flash('alert-class') and return to the subjects route.

Similarly, if a record is not updated then store the failed message in Session::flash('message') and class name in Session::flash('alert-class').

    • destroy() – With this method delete a record from the subjects table by $id and store success message in Session::flash('message') and class name in Session::flash('alert-class') and return to the subjects route.

Completed Code

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;

use App\Subjects;

class SubjectsController extends Controller {

   public function index(){
      $subjects = Subjects::select('id','name','description')->get();
      return view('subjects.index')->with('subjects',$subjects);
   }

   public function create(){
      return view('subjects.create');
   }

   public function store(Request $request){
      $data = $request->except('_method','_token','submit');

      $validator = Validator::make($request->all(), [
         'name' => 'required|string|min:3',
         'description' => 'required|string|min:3',
      ]);

      if ($validator->fails()) {
         return redirect()->Back()->withInput()->withErrors($validator);
      }

      if($record = Subjects::firstOrCreate($data)){
         Session::flash('message', 'Added Successfully!');
         Session::flash('alert-class', 'alert-success');
         return redirect()->route('subjects');
      }else{
         Session::flash('message', 'Data not saved!');
         Session::flash('alert-class', 'alert-danger');
      }

      return Back();
   }

   public function edit($id){
      $subject = Subjects::find($id);

      return view('subjects.edit')->with('subject',$subject);
   }

   public function update(Request $request,$id){
      $data = $request->except('_method','_token','submit');

      $validator = Validator::make($request->all(), [
         'name' => 'required|string|min:3',
         'description' => 'required|string|min:3',
      ]);

      if ($validator->fails()) {
         return redirect()->Back()->withInput()->withErrors($validator);
      }
      $subject = Subjects::find($id);

      if($subject->update($data)){

         Session::flash('message', 'Update successfully!');
         Session::flash('alert-class', 'alert-success');
         return redirect()->route('subjects');
      }else{
         Session::flash('message', 'Data not updated!');
         Session::flash('alert-class', 'alert-danger');
      }

      return Back()->withInput();
   }

   // Delete
   public function destroy($id){
      Subjects::destroy($id);

      Session::flash('message', 'Delete successfully!');
      Session::flash('alert-class', 'alert-success');
      return redirect()->route('subjects');
   }
}

5. View

Create a layout and subjects folder at resources/views/.

Create the following files in the folders –

  • layout
    • app.blade.php
  • subjects
    • index.blade.php
    • create.blade.php
    • edit.blade.php

CRUD view file structure in Laravel 7


layout/app.blade.php

Creating a layout. Included bootstrap CSS in the <head > section and added some CSS.

Define 'content' section.

Completed Code

<!DOCTYPE html>
<html>
<head>

  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <!-- Meta, title, CSS, favicons, etc. -->
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>CRUD (Create Read Update Delete) in a Laravel 7</title>

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" >

  <style type="text/css">
  .errormsg{ color: red; }
  .actionbutton{
      width: 100%;
      height: 55px;
   }
   </style>
</head>
<body>
   <div class="container">
      @yield('content')
   </div>
</body>
</html>

subjects/index.blade.php

Extend 'layout.app' and add content in @section('content').

Display bootstrap alert message if 'message' Session exists. Also, set alert class using 'alert-class' Session.

Add <a > element to open Add subject form. Pass {{route('subjects.create')}} in href attribute.

Create <table > to list records.

Loop on the $subjects and create a row. In the last column added edit and delete links.

Set edit <a > route to {{ route('subjects.edit',[$subject->id]) }} and delete <a > route to {{ route('subjects.delete',[$subject->id]) }}.

Completed Code

<!-- Extends template page-->
@extends('layout.app')

<!-- Specify content -->
@section('content')

<h3>Subjects List</h3>

<div class="row">
   <div class="col-md-12 col-sm-12 col-xs-12">
      <!-- Alert message (start) -->
      @if(Session::has('message'))
      <div class="alert {{ Session::get('alert-class') }}">
         {{ Session::get('message') }}
      </div>
      @endif
      <!-- Alert message (end) -->

      <div class='actionbutton'>

         <a class='btn btn-info float-right' href="{{route('subjects.create')}}">Add</a>

      </div>
      <table class="table" >
        <thead>
          <tr>
            <th width='40%'>Name</th>
            <th width='40%'>Description</th>
            <th width='20%'>Actions</th>
          </tr>
        </thead>
        <tbody>
        @foreach($subjects as $subject)
           <tr>
              <td>{{ $subject->name }}</td>
              <td>{{ $subject->description }}</td>
              <td>
                 <!-- Edit -->
                 <a href="{{ route('subjects.edit',[$subject->id]) }}" class="btn btn-sm btn-info">Edit</a>
                 <!-- Delete -->
                 <a href="{{ route('subjects.delete',$subject->id) }}" class="btn btn-sm btn-danger">Delete</a>
              </td>
           </tr>
        @endforeach
        </tbody>
     </table>

   </div>
</div>
@stop

subjects/create.blade.php

Extend 'layout.app' and add content in @section('content').

Display bootstrap alert message if 'message' Session exists. Also, set alert class using 'alert-class' Session.

Add <a > element to open List of subjects. Pass {{route('subjects')}} in href attribute.

Create <form method="post">. Set its action="{{route('subjects.store')}}".

Create a text and textarea element for entering subject name and description. Display error in <span > if not validated. Also, create a submit button.

Completed Code

<!-- Extends template page -->
@extends('layout.app')

<!-- Specify content -->
@section('content')

<h3>Add Subject</h3>

<div class="row">

   <div class="col-md-12 col-sm-12 col-xs-12">

     <!-- Alert message (start) -->
     @if(Session::has('message'))
     <div class="alert {{ Session::get('alert-class') }}">
        {{ Session::get('message') }}
     </div>
     @endif 
     <!-- Alert message (end) -->

     <div class="actionbutton">

        <a class='btn btn-info float-right' href="{{route('subjects')}}">List</a>

     </div>

     <form action="{{route('subjects.store')}}" method="post" >
        {{csrf_field()}}

        <div class="form-group">
          <label class="control-label col-md-3 col-sm-3 col-xs-12" for="name">Name <span class="required">*</span></label>
          <div class="col-md-6 col-sm-6 col-xs-12">
             <input id="name" class="form-control col-md-12 col-xs-12" name="name" placeholder="Enter subject name" required="required" type="text">

             @if ($errors->has('name'))
               <span class="errormsg">{{ $errors->first('name') }}</span>
             @endif
          </div>
        </div>

        <div class="form-group">
          <label class="control-label col-md-3 col-sm-3 col-xs-12" for="description">Description</label>
          <div class="col-md-6 col-sm-6 col-xs-12">
             <textarea name='description' id='description' class='form-control' placeholder="Enter description"></textarea>

             @if ($errors->has('description'))
                <span class="errormsg">{{ $errors->first('description') }}</span>
             @endif
          </div>
        </div>

        <div class="form-group">
           <div class="col-md-6">

              <input type="submit" name="submit" value='Submit' class='btn btn-success'>
           </div>
        </div>

     </form>

   </div>
</div>
@stop

subjects/edit.blade.php

Extend 'layout.app' and add content in @section('content').

Display bootstrap alert message if 'message' Session exists. Also, set alert class using 'alert-class' Session.

Add <a > element to open List of subjects. Pass {{route('subjects')}} in href attribute.

Create <form method="post">. Set its action="{{route('subjects.update',[$subject->id])}}".

Create a text element and store $subject->name in value attribute. Similarly, create textarea element and store $subject->description. Display error in <span > is not validated. Also, create a submit button.

Completed Code

<!-- Extends template page -->
@extends('layout.app')

<!-- Specify content -->
@section('content')

<h3>Edit Subject</h3>

<div class="row">

   <div class="col-md-12 col-sm-12 col-xs-12">

     <!-- Alert message (start) -->
     @if(Session::has('message'))
     <div class="alert {{ Session::get('alert-class') }}">
        {{ Session::get('message') }}
     </div>
     @endif
     <!-- Alert message (end) -->

     <div class="actionbutton">

        <a class='btn btn-info float-right' href="{{route('subjects')}}">List</a>

     </div>

     <form action="{{route('subjects.update',[$subject->id])}}" method="post" >
{{csrf_field()}}

       <div class="form-group">
         <label class="control-label col-md-3 col-sm-3 col-xs-12" for="description">Name <span class="required">*</span></label>
         <div class="col-md-6 col-sm-6 col-xs-12">
            <input id="name" class="form-control col-md-12 col-xs-12" name="name" placeholder="Enter subject name" required="required" type="text" value="{{old('name',$subject->name)}}">

            @if ($errors->has('name'))
               <span class="errormsg">{{ $errors->first('name') }}</span>
            @endif
         </div>
       </div>

       <div class="form-group">
         <label class="control-label col-md-3 col-sm-3 col-xs-12" for="name">Description
</label>
         <div class="col-md-6 col-sm-6 col-xs-12">
            <textarea name='description' id='description' class='form-control' placeholder="Enter description">{{old('description',$subject->description)}}</textarea>

            @if ($errors->has('description'))
               <span class="errormsg">{{ $errors->first('description') }}</span>
            @endif
         </div>
       </div>

       <div class="form-group">
          <div class="col-md-6">
            <input type="submit" name="submit" value='Submit' class='btn btn-success'>
          </div>
       </div>

     </form>

   </div>
</div>

@stop

6. Output

View Output


7. Conclusion

Follow the same steps to create your new page with the same requirement but not required to create a new layout if you want to use the same layout.

If you found this tutorial helpful then don't forget to share.