es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Error de columna desconocida al usar un nombre de columna personalizado para el correo electrónico – Laravel Fortify

Tengo una base de datos con una columna llamada mail en la tabla de usuarios, pero en Laravel se llama email. Mi problema ahora es la función de olvido de contraseña.

Siempre obtengo el siguiente error:

SQLSTATE[23000]: Violación de integridad del valor de referencia: 
1048 Columna 'email' no puede ser nula 
(SQL: insert into `password_resets` (`email`, `token`, `created_at`) values 
(?, $2y$10$....., 2022-01-03 16:55:22))

Creé una ruta personalizada para el olvido de contraseña, pero de alguna manera no funciona.

Route::post('/forgot-password', function (Request $request) {

    $request->validate([
        'mail' => ['required', 'email'],
        'username' => ['required'],
    ]);
    $status = Password::sendResetLink(
        $request->only('username', 'mail')
    );

    return $status === Password::RESET_LINK_SENT
        ? back()->with(['status' => __($status)])
        : back()->withErrors(['email' => __($status)]);
})->middleware('guest')->name('password.mail');

En el archivo fortify.php configuré email' => 'mail', pero no hay diferencia.
Tal vez hice algo extremadamente estúpido, pero soy nuevo en Laravel.

Entonces, ¿cómo puedo solucionar esto?

No es posible cambiar el nombre de la columna mail a email, y sería tonto crear una segunda columna en la tabla de usuarios llamada email con el mismo contenido.

Saludos.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema aquí es que el método sendResetLink en la fachada Password de Laravel espera que se pase el correo electrónico como email y no como mail, de ahí el mensaje de error.

    Para solucionar esto, puedes sobrescribir el método sendResetLinkEmail en el rasgo ResetsPasswords que Laravel utiliza para la recuperación de contraseñas.

    Para hacer esto, crea un nuevo archivo llamado CustomResetsPasswords.php en tu directorio app/Traits con el siguiente contenido:

    <?php
    
    namespace App\Traits;
    
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Auth;
    use Illuminate\Support\Facades\Password;
    
    trait CustomResetsPasswords
    {
        public function showLinkRequestForm()
        {
            return view('auth.passwords.email');
        }
    
        public function sendResetLinkEmail(Request $request)
        {
            $request->validate(['mail' => 'required|email']);
    
            $response = Password::broker()->sendResetLink(
                $request->only('mail')
            );
    
            if ($response === Password::RESET_LINK_SENT) {
                return back()->with('status', trans($response));
            }
    
            return back()->withErrors(['email' => trans($response)]);
        }
    
        public function showResetForm(Request $request, $token = null)
        {
            return view('auth.passwords.reset')->with(
                ['token' => $token, 'mail' => $request->mail]
            );
        }
    
        public function reset(Request $request)
        {
            $request->validate([
                'mail' => 'required|email',
                'token' => 'required',
                'password' => 'required|confirmed|min:8',
            ]);
    
            $credentials = $request->only(
                'mail', 'password', 'password_confirmation', 'token'
            );
    
            $response = Password::broker()->reset($credentials, function ($user, $password) {
                $user->forceFill([
                    'password' => bcrypt($password)
                ])->save();
    
                Auth::guard($this->getGuard())->login($user);
            });
    
            if ($response === Password::PASSWORD_RESET) {
                return redirect($this->redirectPath())
                            ->with('status', trans($response));
            }
    
            return back()->withErrors(['email' => trans($response)]);
        }
    
        protected function guard() {
            return Auth::guard();
        }
    }
    

    Este código sobrescribe los métodos necesarios en el rasgo ResetsPasswords para usar el atributo mail en lugar del atributo email.

    Luego, en el método boot del AuthServiceProvider, puedes reemplazar el rasgo ResetsPasswords con el rasgo CustomResetsPasswords recién creado.

    use App\Traits\CustomResetsPasswords;
    use Illuminate\Foundation\Auth\ResetsPasswords;
    use Illuminate\Support\Facades\Route;
    use Illuminate\Support\ServiceProvider;
    
    class AuthServiceProvider extends ServiceProvider
    {
        public function boot()
        {
            $this->registerPolicies();
    
            Route::middleware('web')
                ->group(base_path('routes/web.php'));
    
            ResetsPasswords::trait(CustomResetsPasswords::class);
        }
    
        // ....
    }
    

    Esto debería permitirte utilizar la ruta forgot-password con el atributo mail sin ningún problema.

Comments are closed.