Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel redirect from private method with errors

I have the following code:

public function store(Request $request)
{
        $this->validateData($request->all());

        // store something

        return redirect()->action('controller@index')->withMessage( 'Saved Successfully' );
}

private function validateData($requestParams)
{
    try 
    {
        $validator->validate( $requestParams );
    } 
    catch ( ValidationException $e ) 
    {
        redirect()->action('controller@create')->withInput()->withErrors( $e->get_errors() )->send();
        exit(); // this causes the withErrors to not be there
    }
}

If I remove the exit();, the error messages will appear, but also the store function will be executed (see // store something). I know I can rewrite my code like:

if($this->validateData($request->all()))
{
    // store something

    return redirect()->action('controller@index')->withMessage( 'Saved Successfully' );
}

But I don't want the ugly if statement here. There must be a way to redirect with the flash messages without it.

like image 346
pascalvgemert Avatar asked May 28 '15 09:05

pascalvgemert


1 Answers

tl;dr

Update your private method code like this to make the redirection work with $errors variable visible:

private function validateData($requestParams)
{
    try 
    {
        $validator->validate( $requestParams );
    } 
    catch ( ValidationException $e ) 
    {
        $resp = redirect()->action('WelcomeController@index')->withInput()->withErrors($e->get_errors());
        \Session::driver()->save();
        $resp->send();
        exit();
    }
}

explaination

When exiting in the middle of your controller, there are some job which is executed in the application termination will not be execute anymore. In your case, the Session middleware terminate method will not be called. Let see its content (ref):

public function terminate($request, $response)
{
    if ($this->sessionHandled && $this->sessionConfigured() && ! $this->usingCookieSessions())
    {
        $this->manager->driver()->save();
    }
}

Now, look at the save method of our Session driver (ref)

public function save()
{
    $this->addBagDataToSession();
    $this->ageFlashData();
    $this->handler->write($this->getId(), $this->prepareForStorage(serialize($this->attributes)));
    $this->started = false;
}

As you can see, your flash data is only be saved when the Session middleware terminates successfully. With your old code, the flash data will be lost!

What I do with my code is calling the save method manually before sending our response to the browser. However, I still recommend you bring the redirection to the public controller method.

like image 92
Hieu Le Avatar answered Nov 18 '22 01:11

Hieu Le