Customize Laravel Auth (Laravel Breeze Registration and Login)
Tags: php, laravel, beginners, webdev
Published: 2020-12-10 22:36:42

Hello Artisans, after making a post on [Basic Laravel Login and Registration using Laravel Breeze](https://dev.to/kingsconsult/how-to-setup-basic-laravel-app-with-login-and-registration-using-laravel-breeze-6o5), I got a lot of private messages on how to customize the Registration and Login where a developer can be able to add more fields because the default Laravel User Registration fields are just limited to **Name**, **Email** and **Password** right from the time of the Legacy UI till the time of writing this report. But there are instances of where a developer might want to collect not just the name, but **First Name**, **Last Name**, **Username**, **Password** or even making the **Email** not mandatory for users who don't have email, so I decide to write this little piece.
For this article, I am going to use the app from this article [Basic Laravel Login and Registration using Laravel Breeze](https://dev.to/kingsconsult/how-to-setup-basic-laravel-app-with-login-and-registration-using-laravel-breeze-6o5)

Click on my [profile](https://dev.to/kingsconsult) to follow me to get more updates.

### **Step 1: Edit the RegisteredUserController**
Go to **app/Http/Controllers/Auth/RegisteredUserController.php** and customize the **store** method to this
```
    public function store(Request $request)
    {
        $request->validate([
            'firstname' => 'required|string|max:255',
            'lastname' => 'required|string|max:255',
            'password' => 'required|string|confirmed|min:8',
            'username' => 'required|string|max:255',
        ]);

        Auth::login($user = User::create([
            'firstname' => $request->firstname,
            'lastname' => $request->lastname,
            'username' => $request->username,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]));

        event(new Registered($user));

        return redirect(RouteServiceProvider::HOME);
    }
```
In the **validate( )** method, I removed **email**, and added **firstname**, **lastname** and **username**. Also in the **User::create**, I added the new fields.

### **Step 2: Create another migration file to add the new fields to the User and login_history table**
This migration field will add the new fields to our existing **users** table, so run the command below
> php artisan make:migration add_more_fields_to_users_table --table=users

Do the same for the login_history table.
The **--table=users** flag will specify the type of schema facade to use.
A migrations file will be created, go to **database/migrations/** ![Migration files](https://res.cloudinary.com/kingsconsult/image/upload/v1607641943/laravel%20breeze/new/1_gfffcc.png)

### **Step 3: Add the new fields and modify the name field**
We are going to modify the existing name field with firstname and also add other fields, but to modify an existing fields, we need a package **doctrine/dbal**, The Doctrine DBAL library is used to determine the current state of the column and to create the SQL queries needed to make the requested changes to your column. [Laravel docs](https://laravel.com/docs/8.x/migrations#prerequisites)
> composer require doctrine/dbal

After this, update the composer, by running the command below
> composer update

![php artisan command](https://res.cloudinary.com/kingsconsult/image/upload/v1607643312/laravel%20breeze/new/2_g4690b.png)
Then add the following fields to the **up( )** method of the migration file created above
```
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->renameColumn('name', 'firstname');
            $table->string('lastname');
            $table->string('username');
            $table->string('email')->nullable()->change();
        });
    }
```
You will notice how we are going to rename our name field to firstname and added lastname and username, also we modify file email from mandatory to nullable().

Don't forget to do the same for the login_history.
Finally, run the migration command, but  
> php artisan migrate

![php artisan migrate](https://res.cloudinary.com/kingsconsult/image/upload/v1607643462/laravel%20breeze/new/3_e8y5ua.png)
Database 
![Database](https://res.cloudinary.com/kingsconsult/image/upload/v1607643667/laravel%20breeze/new/4_ypf2pa.png)
### **Step 4: Modify the Users Model**
We need to add the fields to be fill in users model, go to **app/Models/User.php** and edit the **protected $fillable** to add the new fields
```
    protected $fillable = [
        'firstname',
        'email',
        'password',
        'username',
        'lastname'
    ];
```
### **Step 5: Modify the Registration view**
Go to **resources/views/auth/register.blade.php** and modify to this
```
<x-guest-layout>
    <x-auth-card>
        <x-slot name="logo">
            <a href="/">
                <x-application-logo class="w-20 h-20 fill-current text-gray-500" />
            </a>
        </x-slot>

        <!-- Validation Errors -->
        <x-auth-validation-errors class="mb-4" :errors="$errors" />

        <form method="POST" action="{{ route('register') }}">
            @csrf

            <!-- Name -->
            <div>
                <x-label for="firstname" :value="__('First Name')" />

                <x-input id="firstname" class="block mt-1 w-full" type="text" name="firstname" required autofocus />
            </div>
            <!-- Name -->
            <div>
                <x-label for="lastname" :value="__('Last Name')" />

                <x-input id="lastname" class="block mt-1 w-full" type="text" name="lastname" required />
            </div>
            <!-- Name -->
            <div>
                <x-label for="username" :value="__('username')" />

                <x-input id="username" class="block mt-1 w-full" type="text" name="username" required />
            </div>

            <!-- Email Address -->
            <div class="mt-4">
                <x-label for="email" :value="__('Email')" />

                <x-input id="email" class="block mt-1 w-full" type="email" name="email"  />
            </div>

            <!-- Password -->
            <div class="mt-4">
                <x-label for="password" :value="__('Password')" />

                <x-input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="new-password" />
            </div>

            <!-- Confirm Password -->
            <div class="mt-4">
                <x-label for="password_confirmation" :value="__('Confirm Password')" />

                <x-input id="password_confirmation" class="block mt-1 w-full" type="password" name="password_confirmation" required />
            </div>

            <div class="flex items-center justify-end mt-4">
                <x-button>
                    {{ __('Register') }}
                </x-button>
            </div>
        </form>
    </x-auth-card>
</x-guest-layout>
```
Start our application with 
> php artisan serve

Click on Register, we are going to have this
![register](https://res.cloudinary.com/kingsconsult/image/upload/v1607644836/laravel%20breeze/new/5_wuabwr.png)

### **Step 6: Modify the Login view**
Go to **resources/views/auth/login.blade.php** and modify to this
```
<x-guest-layout>
    <x-auth-card>
        <x-slot name="logo">
            <a href="/">
                <x-application-logo class="w-20 h-20 fill-current text-gray-500" />
            </a>
        </x-slot>

        <!-- Session Status -->
        <x-auth-session-status class="mb-4" :status="session('status')" />

        <!-- Validation Errors -->
        <x-auth-validation-errors class="mb-4" :errors="$errors" />

        <form method="POST" action="{{ route('login') }}">
            @csrf

            <!-- Email Address -->
            <div>
                <x-label for="username" :value="__('Username')" />

                <x-input id="username" class="block mt-1 w-full" type="text" name="username" required autofocus />
            </div>

            <!-- Password -->
            <div class="mt-4">
                <x-label for="password" :value="__('Password')" />

                <x-input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="current-password" />
            </div>

            <!-- Remember Me -->
            <div class="block mt-4">
                <label for="remember_me" class="flex items-center">
                    <input id="remember_me" type="checkbox" class="form-checkbox" name="remember">
                    <span class="ml-2 text-sm text-gray-600">{{ __('Remember me') }}</span>
                </label>
            </div>

            <div class="flex items-center justify-end mt-4">
                @if (Route::has('password.request'))
                <a class="underline text-sm text-gray-600 hover:text-gray-900" href="{{ route('password.request') }}">
                    {{ __('Forgot your password?') }}
                </a>
                @endif

                <x-button class="ml-3">
                    {{ __('Login') }}
                </x-button>
            </div>
        </form>
    </x-auth-card>
</x-guest-layout>
```
This will change the login field from email to username
### **Step 7: Modify the Login Request Class**
This is the class that replaces the **LoginController** class in the previous Laravel Authentication. Go to **app/Requests/Auth/LoginRequest.php** and change all the email string to username string, and also make sure the validating rules, you remove the email rule and replace it with username rule
```
<?php

namespace App\Http\Requests\Auth;

use Illuminate\Auth\Events\Lockout;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use App\Events\LoginHistory;



class LoginRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'username' => 'required|string',
            'password' => 'required|string',
        ];
    }

    /**
     * Attempt to authenticate the request's credentials.
     *
     * @return void
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    public function authenticate()
    {
        $this->ensureIsNotRateLimited();

        if (! Auth::attempt($this->only('username', 'password'), $this->filled('remember'))) {
            RateLimiter::hit($this->throttleKey());

            throw ValidationException::withMessages([
                'username' => __('auth.failed'),
            ]);
        }

        $user = Auth::user();
        
        event(new LoginHistory($user));

        RateLimiter::clear($this->throttleKey());
    }

    /**
     * Ensure the login request is not rate limited.
     *
     * @return void
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    public function ensureIsNotRateLimited()
    {
        if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
            return;
        }

        event(new Lockout($this));

        $seconds = RateLimiter::availableIn($this->throttleKey());

        throw ValidationException::withMessages([
            'username' => trans('auth.throttle', [
                'seconds' => $seconds,
                'minutes' => ceil($seconds / 60),
            ]),
        ]);
    }

    /**
     * Get the rate limiting throttle key for the request.
     *
     * @return string
     */
    public function throttleKey()
    {
        return Str::lower($this->input('username')).'|'.$this->ip();
    }
}
```

Logout from the app and click on login
![login page](https://res.cloudinary.com/kingsconsult/image/upload/v1607650504/laravel%20breeze/new/6_d0sdcc.png)
![dashboard after login](https://res.cloudinary.com/kingsconsult/image/upload/v1607650645/laravel%20breeze/new/7_fm8xwc.png)

We can now login with username and password instead of email address. That is all
Follow me for more of my articles, you can leave comments, suggestions, and reactions.
I am open to any vacancy as a PHP backend engineer, my strength is in the Laravel framework 

[click the link to view my profile and follow me] (https://dev.to/kingsconsult)