Monday, March 20, 2017

How can I specify an error page after a validation of an HTTP Request coming from an URL that doesn't have a previous page in Laravel?

I am pretty new in PHP and moreover in Laravel. I am working on a Laravel 5.4 project and I have the following problem.

I have the following problem:

After a user registration process my portal send to the user an e-mail containing a link like this to confirm that he really have performed the registration on the system:

http://laravel.dev/activate?email=my-email@gmail.com&token=cce0452d95c358b5b3b97fec5662e12e

As you can see it contains 2 request parameters:

  • email: the email specified during the registration process in the registration form.

  • token: a token generated by the system that will use to check the registration correctness.

Ok, so the registered user receive this e-mail and have to click on this link to confirm its identity.

To validate the correct form of the request (to be handled by the related controller method the request have to contain exactly the email and the token request parameter) I have created this ActivateRequest request performing this shell statment:

php artisan make:request ActivateRequest

and I have added the roles related to check if the request parameter are ok, this is my code:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

/**
 * Class ActivateRequest
 * @package App\Http\Requests
 *
 * Rappresenta una richiesta per l'attivazione di un utente albergatore.
 * La richiestra proviene dal link inviato nella mail e deve contenere come parametri:
 * - Mail con il quale si รจ registrato l'utente.
 * - Il token generato.
 */
class ActivateRequest 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 [
            'email' => 'required|email',
            'token' => 'required',
        ];
    }
}

Then in my web.xml file I have these routes:

Route::get('/', function () {
    return view('welcome');
});

Route::get('contact', function() {
    return View::make('contact');
});

Route::post('contact', 'EnquiryController@index');

Route::resource('/registration', 'RegistrationController');

Route::get('/activate','RegistrationController@activate');

Where this is the route used to activate my user clicking on the link received on the e-mail:

Route::get('/activate','RegistrationController@activate');

and this is the related controller method taking the ActivateRequest object as parameter (so it have enabled the validation feature on it):

public function activate(ActivateRequest $request) {

    return 'Works!';
    // do stuff
}

It works pretty good: if the request is validated (contains an email field and the token field) it enter into the activate() controller method and returns the Works string.

The problem happens if the request is not validated, for example if I send an incomplete request like:

http://laravel.dev/activate?email=my-email@gmail.com

(in this case the token field is missing).

In this case the ActivateRequest object is not validated and correctly doesn't enter into the activate() controller method but the problem is that it come back to the standard Laravel welcome page, the one rendered by this route:

Route::get('/', function () {
    return view('welcome');
});

I think that it happens because this validation happens after that I open a link coming from an e-mail and not coming from a previous page (containing for example a form submission). So Laravel doesn't know where come back and come back to the welcome page.

I also have added this code snippet to show the validation errors message into the welcome page and it works:

        @if (Route::has('login'))
            <div class="top-right links">
                @if (Auth::check())
                    <a href="">Home</a>
                @else
                    <a href="">Login</a>
                    <a href="">Register</a>
                @endif
            </div>
        @endif

So, if the request is not validated, it come back to the welcome page showing the error message.

But I don't like it. It is dirty. Can I specify a specific page to come back in case of error instead the Laravel welcome page? I think that the problem is that in this case there is not a "previous page" (it is the e-mail) so Laravel automatically come back to the welcome page when an error occurs.



via Andrea Nobili

Advertisement