This tutorial is part of the Laravel Handbook. Download it from https://flaviocopes.com/access/

In this tutorial, we will be implementing the ability for authenticated users to add items to the database. Unlike our previous project, this time we will display the list of dogs even when users are logged out, but only logged-in users will have permission to modify the data.

To begin, let’s create a new migration for the “dogs” table:

php artisan make:migration create_dogs_table

Open the newly created migration file, which is located at database/migrations/2023_05_12_164831_create_dogs_table.php, and update it as follows:

<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('dogs', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }

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

Save the file and run php artisan migrate in your terminal to apply the migration.

Next, let’s scaffold the “Dog” model:

php artisan make:model Dog

In the routes/web.php file, add the following line at the top to import the Dog model:

use App\Models\Dog;

Then, locate the / route and update it as follows, which retrieves the list of dogs and passes it to the “welcome” view:

Route::get('/', function () {
    $dogs = Dog::all();
    return view('welcome', ['dogs' => $dogs]);
})->name('index');

Now, open the resources/views/welcome.blade.php file and modify it to loop over the dogs array using @foreach directive:

<h1 class="pb-2 mb-3 font-bold border-b border-b-gray-300">
    Dogs
</h1>

<div>
    @foreach ($dogs as $dog)
    <li class="flex mb-1">
        <span class="flex-1">{{ $dog->name }}</span>
    </li>
    @endforeach

    @auth
    <p>Logged in</p>
    @endauth

    @guest
    <p>Not logged in</p>
    @endguest
</div>

Now, if you refresh the home page, you’ll see the list of dogs. However, since we don’t have any dogs in the database yet, the list will be empty.

To display an “empty state” when there are no dogs, you can use the @forelse directive instead of @foreach. Update the code in resources/views/welcome.blade.php as follows:

@forelse ($dogs as $dog)
<li class="flex mb-1">
    <span class="flex-1">{{ $dog->name }}</span>
</li>
@empty
<p>No dogs yet</p>
@endforelse

To add some dogs to the database, you can use SQL queries in a tool like TablePlus. Here’s an example SQL query to insert some dog data:

INSERT INTO "dogs" ("id", "name", "created_at", "updated_at") VALUES
('1', 'Roger', '2023-05-11 09:27:20', '2023-05-11 09:27:20'),
('2', 'Syd', '2023-05-11 09:29:52', '2023-05-11 09:29:52'),
('3', 'Botolo', '2023-05-11 09:29:57', '2023-05-11 09:29:57'),
('4', 'Zoe', '2023-05-11 09:30:12', '2023-05-11 09:30:12');

Now, we’ll add the ability to add and delete dogs. First, let’s update the Dog model to include the name attribute in the $fillable array:

protected $fillable = ['name'];

Next, let’s create a controller named DogController:

php artisan make:controller DogController

Inside the DogController.php file, add the following lines at the top to import the necessary classes:

use App\Models\Dog;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;

Then, add the create and delete methods to the DogController class, which will handle the logic for adding and deleting dogs. Both methods will first check if the user is logged in before performing any actions:

public function create(Request $request)
{
    if (Auth::check()) {
        $this->validate($request, [
            'name' => 'required',
        ]);
        Dog::create($request->all());
    }
    return redirect()->route('index');
}

public function delete($id)
{
    if (Auth::check()) {
        $dog = Dog::find($id);
        $dog->delete();
    }

    return redirect()->route('index');
}

Next, add the routes for creating and deleting dogs in the routes/web.php file:

use App\Http\Controllers\DogController;

//...

Route::post(
    '/dogs',
    [DogController::class, 'create']
)->name('dog.create');

Route::delete(
    '/dog/{id}',
    [DogController::class, 'delete']
)->name('dog.delete');

Finally, update the resources/views/welcome.blade.php file to include buttons for deleting dogs and a form for adding new dogs:

@forelse ($dogs as $dog)
<li class="flex mb-1">
    <span class="flex-1">{{ $dog->name }}</span>
    @auth
    <form action="{{ route('dog.delete', $dog->id) }}" method="POST">
        @csrf
        @method('DELETE')
        <button type="submit" class="p-1 bg-gray-200 border border-black">Delete</button>
    </form>
    @endauth
</li>
@empty
<p>No dogs yet</p>
@endforelse

@auth
<form method="post" action="{{ route('dog.create') }}">
    @csrf
    <h3 class="pb-2 mt-4 mb-3 font-bold border-b border-b-gray-300">Add a new dog</h3>
    <div class="flex">
        <div class="flex-1">
            <label>Name</label>
            <input type="text" name="name" id="name" class="p-1 border border-gray-200">
        </div>
        <input type="submit" name="send" value="Submit" class="p-1 bg-gray-200 border border-black cursor-pointer">
    </div>
</form>
@endauth

That’s it! Now, when logged in, you’ll see a form to add a new dog and a delete button next to each dog in the list. When logged out, you will only see the list of dogs.

Tags: Laravel, Authentication, Database, CRUD