I want to log in using my phone number or email in Laravel 11 with Breeze.
┌──────────────────────────────────────────────┐
│ │
│ │
│ │
│ Email Or Mobile │
│ [__________________________________] │
│ │
│ │
│ Password │
│ [__________________________________] │
│ │
│ │
│ [ ] Remember me │
│ │
│ .─────────. │
│ <Forgot your password?> │ LOG IN │ │
│ `─────────´ │
│ │
└──────────────────────────────────────────────┘
This is a picture of what I want to do
But what is stopping me is how I will do this thing inside LoginRequest.php file of Laravel 11.
LoginRequest.php file:
This is the official file that comes with Laravel 11 when you install Breeze
<?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;
class LoginRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'email' => ['required', 'email','exists:users,email'],
'password' => ['required', 'string'],
];
}
public function messages(): array
{
return [
'email.exists' => 'unavailable',
];
}
/**
* Attempt to authenticate the request's credentials.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function authenticate(): void
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'email' => trans('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
}
/**
* Ensure the login request is not rate limited.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function ensureIsNotRateLimited(): void
{
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
return;
}
event(new Lockout($this));
$seconds = RateLimiter::availableIn($this->throttleKey());
throw ValidationException::withMessages([
'email' => trans('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]),
]);
}
/**
* Get the rate limiting throttle key for the request.
*/
public function throttleKey(): string
{
return Str::transliterate(Str::lower($this->string('email')).'|'.$this->ip());
}
}
I was able to do what I wanted and wanted to share it with you so that everyone can benefit from it. What I did was simply filter the value that comes from the request and check if it is an email or not.
First, a variable named identify was created to take the value of email or mobile on behalf of the verification and filtering of the value that comes from the request. If the value that comes from the request is an email, the value of the variable identify that was created will be equal to email.
If the value coming from the request is not an email, a value named mobile will be stored inside the same variable named identify.
And the value that is inside the identify variable is used, i.e. if the value is email or mobile
It is placed inside validation to check if the value that comes from the request is present in the users table in the database or not Like this:
public function rules(): array
{
$this->identify = filter_var(request()->input('identify') , FILTER_VALIDATE_EMAIL ) ? "email" : 'mobile';
return [
'identify' => ['required', 'string',"exists:users,$this->identify"],
'password' => ['required', 'string'],
];
}
public function messages(): array
{
return [
'identify.exists' => 'unavailable',
];
}
Then change the authentication method inside the authenticate function inside the if condition to change my authentication method Auth::attempt and make it look like this:
if (!Auth::attempt([$this->identify => request()->input('identify'), 'password' => request()->input('password')], $this->boolean('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'identify' => trans('auth.failed'),
]);
}
What was done here is to take the value inside the identify variable and put it inside Auth::attempt and make its value the value that comes from request and also the same thing with the password it will be as it is nothing changed in it I just added it inside the list so that there are no problems or objections or errors in the code and made its value equal to the value that comes from request
This way I solved the problem I was facing and did what I wanted to do.
If there is any query or if there is a better way in mind please feel free to share it for everyone to benefit from. Thank you.