If you want to override behaviour of \Illuminate\Auth\Passwords\DatabaseTokenRepository
methods, you will have to build your own token repository, overriding methods in the existing repository that currently just check for the 'email' column in the database. Ensure you've created a migration to add the appropriate column:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
$tname = config("auth.passwords.users.table");
Schema::table($tname, fn (Blueprint $t) => $t->string("mobile", 16));
}
public function down(): void
{
$tname = config("auth.passwords.users.table");
Schema::table($tname, fn (Blueprint $t) => $t->dropColumn("mobile"));
}
}
Then create your custom repository:
app/Auth/DatabaseTokenRepository.php
<?php
namespace App\Auth;
use Illuminate\Auth\Passwords\DatabaseTokenRepository as DatabaseTokenRepositoryBase;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Support\Carbon;
class DatabaseTokenRepository extends DatabaseTokenRepositoryBase;
{
//
// Override these methods to use mobile as well as email
//
public function create(CanResetPasswordContract $user)
{
$email = $user->getEmailForPasswordReset();
$mobile = $user->getMobileForPasswordReset();
$this->deleteExisting($user);
$token = $this->createNewToken();
$this->getTable()->insert($this->getPayload($email, $mobile, $token));
return $token;
}
protected function deleteExisting(CanResetPasswordContract $user)
{
return $this->getTable()
->where("email", $user->getEmailForPasswordReset())
->orWhere("mobile", $user->getMobileForPasswordReset())
->delete();
}
protected function getPayload($email, $mobile, $token): array
{
return [
"email" => $email,
"mobile" => $mobile,
"token" => $this->hasher->make($token),
"created_at" => new Carbon(),
];
}
public function exists(CanResetPasswordContract $user, $token)
{
$record = (array) $this->getTable()
->where("email", $user->getEmailForPasswordReset())
->orWhere("mobile", $user->getMobileForPasswordReset())
->first();
return $record &&
! $this->tokenExpired($record["created_at"]) &&
$this->hasher->check($token, $record["token"]);
}
public function recentlyCreatedToken(CanResetPasswordContract $user)
{
$record = (array) $this->getTable()
->where("email", $user->getEmailForPasswordReset())
->orWhere("mobile", $user->getMobileForPasswordReset())
->first();
return $record && $this->tokenRecentlyCreated($record['created_at']);
}
}
Now you will need to use this custom token repository instead of the default one. So you have to override another class.
app/Auth/PasswordBrokerManager.php
<?php
namespace App\Auth;
use Illuminate\Support\Str;
use Illuminate\Auth\Passwords\PasswordBrokerManager as PasswordBrokerManagerBase;
class PasswordBrokerManager extends PasswordBrokerManagerBase
{
protected function createTokenRepository(array $config)
{
$key = $this->app['config']['app.key'];
if (Str::startsWith($key, 'base64:')) {
$key = base64_decode(substr($key, 7));
}
$connection = $config['connection'] ?? null;
// return an instance of your new repository
// it's in the same namespace, no need to alias it
return new DatabaseTokenRepository(
$this->app['db']->connection($connection),
$this->app['hash'],
$config['table'],
$key,
$config['expire']
);
}
}
Now you have created a custom broker to use your custom repository. You need a new service provider to make use of it.
app/Providers/PasswordResetServiceProvider.php
<?php
namespace App\Providers;
use App\Auth\PasswordBrokerManager;
use Illuminate\Auth\Passwords\PasswordResetServiceProvider as PasswordResetServiceProviderBase;
class PasswordResetServiceProvider extends PasswordResetServiceProviderBase
{
protected function registerPasswordBroker()
{
$this->app->singleton('auth.password', function ($app) {
// reference your new broker
// the rest of the method code is unchanged
return new PasswordBrokerManager($app);
});
$this->app->bind('auth.password.broker', function ($app) {
return $app->make('auth.password')->broker();
});
}
}
Next, replace default password reset service provider with the custom one in your application config:
app/config/app.php
<?php
return [
"providers" => [
...
// Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
App\Providers\PasswordResetServiceProvider::class,
...
],
];
And finally, define the getMobileForPasswordReset()
method on your user model:
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
...
class User extends Authenticatable
{
...
public method getMobileForPasswordReset()
{
return $this->mobile;
}
}