DEV Community

Alpha Olomi
Alpha Olomi

Posted on • Updated on

Laravel 9 x CRUD with Tests

Hi there,

In this tutorial, we will see how to create a web application using Laravel version 9. We will build a application from scratch.

We will create a Product CRUD application.

We will use Bootstrap 5 for Styling.

Step 1: Create new Laravel application

Using the Laravel installer to create a new application.

laravel new shop-app
cd shop-app
Enter fullscreen mode Exit fullscreen mode

Step 2: Database Configuration

We will update database configuration, we need to add database name, mysql username and password.

Open .env file and fill all details like as bellow:

file: .env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog
DB_USERNAME=root
DB_PASSWORD=""
Enter fullscreen mode Exit fullscreen mode

Step 3: Create Migrations

Here, we will create products table using laravel migration. so let's use following command to create migration file.

php artisan make:migration create_products_table --create=products
Enter fullscreen mode Exit fullscreen mode

A file in "database/migrations" will be generated

<?php
// ...
public function up() {
    Schema::create('products',  function  (Blueprint $table)  {
        $table->id();
        $table->string('name');
        $table->text('detail');
        $table->timestamps();
    });

}
// ....
Enter fullscreen mode Exit fullscreen mode
php artisan migrate
Enter fullscreen mode Exit fullscreen mode

Step 4: Create Controller and Model

We create a new resource controller named ProductController.

php artisan make:controller ProductController --resource --model=Product
Enter fullscreen mode Exit fullscreen mode

A new file app/Http/Controllers/ProductController.php.

In this controller there will seven methods by default as bellow methods:

  • 1) index()
  • 2) create()
  • 3) store()
  • 4) show()
  • 5) edit()
  • 6) update()
  • 7) destroy()

Copy code below and put on ProductController.php file.

file: app/Http/Controllers/ProductController.php

<?php

namespace App\Http\Controllers;

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

class ProductController extends Controller {

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

    $products = Product::latest()->paginate(5);

    return view('products.index')
      ->with('products',$products);

  }

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

  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public  function store(Request $request) {
    $data = $request->validate([
      'name'  =>  'required|string',
      'detail'  =>  'required|string',
    ]);
    Product::create($data);

    return redirect()->route('products.index')
      ->with('success','Product created successfully.');

  }

  /**
   * Display the specified resource.
   *
   * @param  \App\Models\Product  $product
   * @return \Illuminate\Http\Response
   */
  public  function show(Product $product) {

      return view('products.show',compact('product'));

  }

  /**
   * Show the form for editing the specified resource.
   *
   * @param  \App\Models\Product  $product
   * @return \Illuminate\Http\Response
   */
  public  function edit(Product $product) {

    return view('products.edit',compact('product'));

  }

  /**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \App\Models\Product  $product
   * @return \Illuminate\Http\Response
   */
  public  function update(Request $request,  Product $product) {
    $data = $request->validate([
      'name'  =>  'required',
      'detail'  =>  'required',
    ]);

    $product->update($data);
    return redirect()->route('products.index')
      ->with('success','Product updated successfully');
  }

  /**
 * Remove the specified resource from storage.
 *
 * @param  \App\Models\Product  $product
 * @return \Illuminate\Http\Response
 */
  public  function destroy(Product $product) {

    $product->delete();
    return redirect()->route('products.index')
      ->with('success','Product deleted successfully');
  }

}
Enter fullscreen mode Exit fullscreen mode

file: app/Models/Product.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{

  use HasFactory;

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

}
Enter fullscreen mode Exit fullscreen mode

Step 5: Add Resource Route

Here, we need to add resource route for product crud.
Open your routes/web.php file and add following route.

file: routes/web.php

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;

// ...skippped
Route::resource('products',  ProductController::class);
Enter fullscreen mode Exit fullscreen mode

Step 6: Add Blade Files

In last step. In this step we have to create just blade files. So mainly we have to create layout file and then create new folder "products" then create blade files of crud app. So finally you have to create following bellow blade file:

  • 1). layout.blade.php
  • 2). index.blade.php
  • 3). create.blade.php
  • 4). edit.blade.php
  • 5). show.blade.php

So let's just create following file and put bellow code.

file: resources/views/products/layout.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Laravel Application</title>
 <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    @yield('content')
</div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

file: resources/views/products/index.blade.php

@extends('products.layout')

@section('content')
  <div  class="row">
  <div  class="col-lg-12 margin-tb">
    <div  class="pull-left">
       <h2>Laravel Shop | All Products</h2>
    </div>
    <div  class="pull-right">
        <a  class="btn btn-success" href="{{ route('products.create') }}"> Create New Product</a>
    </div>
  </div>
  </div>
 @if ($message = Session::get('success'))
  <div  class="alert alert-success"> 
    <p>{{ $message }}</p>
  </div>
 @endif

  <table class="table table-bordered">
  <tr>
    <th>No.</th>
    <th>Name</th>
    <th>Details</th>
    <th width="280px">Action</th>
  </tr>
  @foreach ($products as $product)
  <tr>
    <td>{{ $loop->iteration }}</td>
    <td>{{ $product->name }}</td>
    <td>{{ $product->detail }}</td>
    <td>
    <form  action="{{ route('products.destroy',$product->id) }}" method="POST">
    <a class="btn btn-info" href="{{ route('products.show',$product->id) }}">Show</a>
    <a class="btn btn-primary" href="{{ route('products.edit',$product->id) }}">Edit</a>
       @csrf
       @method('DELETE')
     <button type="submit" class="btn btn-danger">Delete</button>
    </form>
    </td>
  </tr>
 @endforeach
  </table>
 {!! $products->links() !!}
@endsection
Enter fullscreen mode Exit fullscreen mode

file: resources/views/products/create.blade.php

@extends('products.layout')

@section('content')
<div  class="row">
  <div  class="col-lg-12 margin-tb">
      <div  class="pull-left">
         <h2>Add New Product</h2>
      </div>
      <div class="pull-right">
          <a class="btn btn-primary"  href="{{ route('products.index') }}"> Back</a>
      </div>
  </div>
</div>

@if ($errors->any())
  <div  class="alert alert-danger">
    <strong>Whoops!</strong> There were some problems with your input.<br><br>
    <ul>
       @foreach ($errors->all() as $error)
         <li>{{ $error }}</li>
       @endforeach
    </ul>
  </div>
@endif

<form  action="{{ route('products.store') }}"  method="POST">

 @csrf
  <div class="row">
    <div class="col-xs-12 col-sm-12 col-md-12">
      <div class="form-group">
      <strong>Name:</strong>
      <input  type="text"  name="name"  class="form-control"  placeholder="Name">
    </div>
  </div>
  <div class="col-xs-12 col-sm-12 col-md-12">
    <div class="form-group">
      <strong>Detail:</strong>
      <textarea  class="form-control"  style="height:150px"  name="detail"  placeholder="Detail"></textarea>
    </div>
  </div>
  <div  class="col-xs-12 col-sm-12 col-md-12 text-center">
    <button  type="submit"  class="btn btn-primary">Submit</button>
  </div>
  </div>
</form>
@endsection
Enter fullscreen mode Exit fullscreen mode

file: resources/views/products/edit.blade.php

@extends('products.layout')

@section('content')
  <div class="row">
      <div class="col-lg-12 margin-tb">
          <div class="pull-left">
              <h2>Edit Product</h2>
          </div>
          <div  class="pull-right">
              <a  class="btn btn-primary"  href="{{ route('products.index') }}"> Back</a>
          </div>
      </div>
  </div>
 @if ($errors->any())
  <div  class="alert alert-danger">
     <strong>Whoops!</strong> There were some problems with your input.<br><br>
    <ul>
       @foreach ($errors->all() as $error)
         <li>{{ $error }}</li>
       @endforeach
    </ul>
  </div>
 @endif

  <form  action="{{ route('products.update',$product->id) }}" method="POST">
     @csrf
     @method('PUT')
  <div  class="row">
  <div  class="col-xs-12 col-sm-12 col-md-12">
    <div  class="form-group">
    <strong>Name:</strong>
    <input  type="text"  name="name"  value="{{ $product->name }}" class="form-control" placeholder="Name">
    </div>
  </div>
  <div  class="col-xs-12 col-sm-12 col-md-12">
    <div  class="form-group">
    <strong>Detail:</strong>
    <textarea  class="form-control"  style="height:150px"  name="detail"  placeholder="Detail">{{ $product->detail }}</textarea>
    </div>
  </div>
  <div  class="col-xs-12 col-sm-12 col-md-12 text-center">
    <button  type="submit"  class="btn btn-primary">Submit</button>
  </div>
  </div>
  </form>
@endsection
Enter fullscreen mode Exit fullscreen mode

file: resources/views/products/show.blade.php

@extends('products.layout')

@section('content')
  <div class="row">
  <div class="col-lg-12 margin-tb">
    <div class="pull-left">
      <h2>Show Product</h2>
    </div>
    <div  class="pull-right">
      <a  class="btn btn-primary"  href="{{ route('products.index') }}"> Back</a>
    </div>
  </div>
  </div>
  <div class="row">
  <div class="col-xs-12 col-sm-12 col-md-12">
    <div class="form-group">
      <strong>Name:</strong>
      {{ $product->name }}
    </div>
  </div>
  <div class="col-xs-12 col-sm-12 col-md-12">
    <div class="form-group">
    <strong>Details:</strong>
      {{ $product->detail }}
    </div>
  </div>
  </div>
@endsection
Enter fullscreen mode Exit fullscreen mode

Run Laravel App:

Start the delevelopment server

php artisan serve
Enter fullscreen mode Exit fullscreen mode

Now, Go to your web browser, type the given URL and view the app output:

http://localhost:8000/products

Stay tuned to Part 2 Testing using PHP Pest

Happy Coding!

Discussion (4)

Collapse
sheddyowden profile image
Sheddy Owden

Usefull

Collapse
frank255 profile image
Frank Ilunga

Very helpful tutorial ๐Ÿ™

Collapse
0733349974 profile image
0733349974

I appreciateโœŠ what you are doing & radiate love all days long

Collapse
alphaolomi profile image
Alpha Olomi Author

Thank you! More coming follow to stay updated.