Redirigir a un usuario a la página que estaba viendo (o a otra, en Laravel)

De pronto un usuario necesita iniciar sesión o registrarse en nuestra aplicación. ¡Nos interesa que no se pierda de lo que estaba haciendo!

Introducción

Por defecto el middleware auth que Laravel define se encarga de hacer una redirección, para que el usuario vuelva a la página a la que estaba tratando de acceder.

Aunque esto funciona correctamente con peticiones GET, no funciona adecuadamente con peticiones POST donde se envían ciertos datos.

Es por ello que, hay ocasiones en las que nos conviene anticipar estas situaciones, y sería ideal que Laravel nos entienda si le decimos lo siguiente:

Lleva al usuario al formulario de inicio de sesión. Dile que inicie sesión antes de continuar. Si aún no se ha registrado, ofrécele un enlace para que lo pueda hacer. Luego tráelo de vuelta a esta página.

Sería genial poder enviar al usuario a un enlace de login (como los 2 siguientes ejemplos) y que sea redirigido a la URL o ruta indicada, incluso si se acaba de registrar:

mi-aplicacion.com/login?redirect_to=/ruta/donde/estaba
mi-aplicacion.com/login?redirect_to=mi-aplicacion.com/ruta/distinta/segun/convenga

Pues eso es justamente lo que vamos a hacer ahora.

Paso 1

Debemos anticiparnos a la situación y generar el enlace correspondiente para usuarios que aún no han iniciado sesión en nuestra aplicación.

Por ejemplo, supongamos que estoy desarrollando una aplicación que permite buscar empleo. Esta aplicación permite a los interesados postular a las ofertas de trabajo.

Postular a un trabajo en mi aplicación

Me interesa que:

  • Si el usuario ya ha iniciado sesión, entonces se realice una petición POST sobre la ruta que permite postular a trabajos.
  • Si el usuario aún no ha iniciado sesión, sea llevado a una página de login y que pueda registrarse en caso que no lo haya hecho aún. Pero que a pesar de todo, vuelva a donde se encontraba antes.

Entonces en mi caso prepararía la vista de la siguiente forma:

@if (auth()->check())
    <form action="{{ url('/job/'.$job->id.'/apply') }}" method="post">
        <button type="submit" class="btn blue no-margin">
            Postular al trabajo
        </button>
    </form>
@else
    <a href="{{ url('/login?redirect_to='.url()->current()) }}" class="btn blue no-margin">
        Postular al trabajo
    </a>
@endif

Hasta aquí hay que tener en cuenta lo siguiente:

  • Yo estoy usando url()->current() para obtener la URL actual, de tal forma que el usuario regrese a esta página luego de autenticarse.
  • Sin embargo, se podría usar una URL (o ruta) totalmente distinta (según lo necesites).

Paso 2

Si el usuario ya había iniciado sesión, entonces el formulario realiza una petición POST y no hay nada nuevo.

Pero si no hay ningún usuario autenticado, entonces el enlace enviará al usuario a una ruta como la siguiente:

http://tawa.dev.pe:8080/login?redirect_to=http://tawa.dev.pe:8080/empleo/fullstack-developer/2

De seguro ya notaste que:

  • De forma local trabajo con el puerto 8080
  • Tengo un Virtual Host configurado para el host name tawa.dev.pe
  • La URL del empleo al que se intenta postular es http://tawa.dev.pe:8080/empleo/fullstack-developer/2

En fin. Continuemos.

En este segundo paso, debemos preparar a nuestra página de login para que entienda e interprete el parámetro redirect_to.

¿Cómo hacemos eso? ¡Exacto! En LoginController (se encuentra en app/Http/Controllers/Auth).

Si no has hecho ningún cambio, el controlador tendrá este aspecto:

class LoginController extends Controller
{
    use AuthenticatesUsers;

    protected $redirectTo = '/home';

    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }
}

Respecto al controlador, debes tener en cuenta lo siguiente:

  • El atributo $redirectTo permite definir una ruta, para que todo usuario sea redirigido allí luego de iniciar sesión.
  • Esta lógica está definida en Laravel, por defecto, si hemos usado php artisan make:auth para generar nuestro sistema de autenticación.
  • De forma específica esta lógica se encuentra definida dentro del trait AuthenticatesUsers.

Nosotros necesitamos que los usuarios sean redirigidos a una ruta dinámica, en caso que se haya solicitado una redirección. Y que se continúe usando la ruta constante definida por el atributo $redirectTo de caso contrario.

Para lograr esto vamos a sobreescribir 2 métodos.

Por lo tanto añadimos los siguientes 2 métodos sobre nuestro LoginController:

public function showLoginForm(IlluminateRequest $request)
{
    if ($request->has('redirect_to')) {
        session()->put('redirect_to', $request->input('redirect_to'));
    }

    return view('auth.login');
}

public function redirectTo()
{
    if (session()->has('redirect_to'))
        return session()->pull('redirect_to');

    return $this->redirectTo;
}

Aquí:

  • El método showLoginForm es llamado cuando un usuario visita la página de inicio de sesión.
  • Entonces creamos una variable de sesión llamada redirect_to en caso que exista un parámetro con el mismo nombre.
  • El método redirectTo es llamado cuando llega el momento de redirigir al usuario.
  • Naturalmente sólo se redirige a la ruta indicada en el atributo redirectTo. Pero nosotros estamos sobreescribiendo el método, para que, en caso de existir una variable de sesión, se use el valor de esta variable y de paso deje de existir (ya que eso hace pull, devolver el valor y eliminar la variable de sesión).

Paso 3

Lo que hicimos en el paso 2 sirve para que un usuario sea redirigido a la página indicada en el parámetro redirect_to (que es enviado a la ruta /login).

Si queremos que el usuario sea redirigido según el valor de dicho parámetro, incluso si se acaba de registrar, debemos también aplicar un cambio en RegisterController (para que haga caso a nuestra variable de sesión, la que creamos en LoginController).

Entonces en RegisterController también sobreescribimos el método redirectTo:

public function redirectTo()
{
    if (session()->has('redirect_to'))
        return session()->pull('redirect_to');

    return $this->redirectTo;
}

Recapitulando

Finalmente, vamos a verificar que todo funcione correctamente.

  • Ahora mismo, acabo de dar clic sobre el botón para Postular.
  • Como no había una sesión activa fui redirigido a http://tawa.dev.pe:8080/login?redirect_to=http://tawa.dev.pe:8080/empleo/fullstack-developer/2.
  • Como "aún no me registro", lo voy a hacer ahora dando clic al enlace correspondiente. Inicio de sesión y registro
  • El enlace de registro me llevó a http://tawa.dev.pe:8080/register. Pero, aunque se ha perdido el parámetro GET de la URL, la variable de sesión sigue existiendo. Así que no hay problema.
  • Ingresé mis datos. Me registré. Y he sido redirigido a la página donde antes me encontraba. Es decir he vuelto a http://tawa.dev.pe:8080/empleo/fullstack-developer/2.
  • Ahora si presiono el botón Postular podré hacerlo (pero esa es ya, otra historia).

laravel

Cursos recomendados

Curso de Laravel 5.5

Aprende Laravel

Aprende Laravel 5.5 desde cero y desarrolla aplicaciones web reales, en tiempo récord, de la mano de Laravel.

Ver más
Curso práctico de Javascript

Aprende Javascript

Domina JS con este curso práctico y completo! Fundamentos, ejemplos reales, ES6+, POO, Ajax, Webpack, NPM y más.

Ver más
Curso de Laravel, Vue.js y Pusher

Aprende Vue.js

Desarrollemos un Messenger! Aprende sobre Channels, Queues, Vuex, JWT, Sesiones, BootstrapVue y mucho más.

Ver más
Logo de Programación y más

¿Tienes alguna duda?

Si algo no te quedó claro o tienes alguna sugerencia, escribe un comentario aquí debajo.

Además recuerda compartir el post si te resultó de ayuda. ¡Gracias!

Antes que te vayas

Inscríbete en nuestro curso gratuito de Laravel