Skip to content

Only authenticated users can add items to the database

The Valley of Code

Your Web Development Manual

Now let’s re-implement what we did in the first project but this time we show the dogs list when logged out, but we’ll only allow logged in users to modify the data.

First we create a new migration:

php artisan make:migration create_dogs_table

Open the newly created migration file, in my case database/migrations/2023_05_12_164831_create_dogs_table.php

<?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->timestamps();
        });
    }

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

We just modify the migration a little adding a name for the dog:

Schema::create('dogs', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->timestamps();
});

Save the file, go back to the terminal, run php artisan migrate

Now we scaffold the Dog model:

php artisan make:model Dog

Go to routes/web.php.

At the top, add

use App\Models\Dog;

then find the / route:

Route::get('/', function () {
    return view('welcome');
});

and change it to this to retrieve the dogs list and pass it to the view, which we label index:

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

Now in resources/views/welcome.blade.php we can loop over the dogs array using @foreach like this:

<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>

If you refresh the home you’ll see nothing changed because we don’t have any dog in the list.

We can actually show an “empty state” using @forelse.

Instead of

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

use this:

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

We don’t have dogs in the table yet, but you can open the database using TablePlus and insert data using this SQL query:

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 when we’re logged in I want to display the form to add a new dog, and the delete button for each dog in the list.

First, inside the Dog model class we add the name to an array named $fillable:

protected $fillable = ['name'];
<?php

namespace App\Models;

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

class Dog extends Model
{
    use HasFactory;
		protected $fillable = ['name'];
}

We create a controller named DogController:

php artisan make:controller DogController

This created the app/Http/Controllers/DogController.php file:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class DogController extends Controller
{
    //
}

Add use App\Models\Dog; at the top, and add those 2 methods to the class, create and delete, as we did before, but this time both first check that the user is logged in:

<?php

namespace App\Http\Controllers;

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

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

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

        return to_route('index');
    }
}

Ok now we need a route to add a a new dog, and one to delete a dog. In routes/web.php, add:

use App\Http\Controllers\DogController; 

//...

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

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

Now we can display the buttons to remove dogs in resources/views/welcome.blade.php:

@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

We wrap it into @auth to make it only visible if logged in.

Try clicking one “delete” button, the corresponding row should disappear.

If logged out, here’s what you see:

Now let’s add the form to add a new dog. Before we used a partial, to see how you can use partials, but now let’s just add it to the welcome template:

@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

Here’s the full code for reference:

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    @vite('resources/css/app.css')
</head>

<body class="p-4">

    @if (Route::has('login'))
        <div class="text-right">
            @auth
                <a href="{{ url('/dashboard') }}" class="">Dashboard</a>
            @else
                <a href="{{ route('login') }}" class="">Log in</a>
                @if (Route::has('register'))
                    <a href="{{ route('register') }}" class="ml-4">Register</a>
                @endif
            @endauth
        </div>
    @endif

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

    <ul>
        @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
    </ul>

    @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

</body>

</html>

→ Get my Laravel Handbook
  • THE VALLEY OF CODE (+ PRO), your web development manual
  • I wrote 15+ free coding BOOKS, download them here
  • SOLOPRENEUR LAND the missing MBA for wannabe solopreneurs craving a life with more freedom, control, fulfillment and purpose (summer 2024)