Laravel从私有方法重定向错误


Laravel redirect from private method with errors

我有以下代码:

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
    }
}

如果我删除exit();,将出现错误消息,但也将执行存储功能(参见// store something)。我知道我可以这样重写我的代码:

if($this->validateData($request->all()))
{
    // store something
    return redirect()->action('controller@index')->withMessage( 'Saved Successfully' );
}

但是我不想在这里使用难看的if语句。必须有一种方法来重定向没有它的flash消息

br

像这样更新您的私有方法代码,使重定向工作与$errors变量可见:

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();
    }
}

解释

在控制器中间退出时,有一些在应用程序终止时执行的作业将不再执行。在您的示例中,不会调用会话中间件terminate方法。让我们看看它的内容(ref):

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

现在,看看会话驱动程序(ref)

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

可以看到,只有当Session中间件成功终止时,flash数据才会被保存。使用旧代码,flash数据将丢失!

我对我的代码所做的是在向浏览器发送响应之前手动调用save方法。但是,我仍然建议您将重定向带到公共控制器方法。

我不认为使用if语句有任何问题。基本上你不会停止代码的执行,这就是为什么store函数会被执行,即使你的验证失败。重定向函数只发送一个带有重定向位置的标头,它不会在执行后中止代码。它与exit()一起工作,因为它发送重定向头并停止要执行的其余代码。

这不是丑陋的,它是干净和清晰的,我建议你使用它。这是正确使用if语句的一个很好的例子——如果我满足了一个条件,那么就这样做。在您的例子中,如果验证通过,只需存储对象。(请记住修改您的验证函数以返回true或false)

if($this->validateData($request->all()))
{
    // store something
    return redirect()->action('controller@index')->withMessage( 'Saved Successfully' );
}

另一个可能的解决方案是像这样使用try .. catch

public function store(Request $request)
{
    try {
        $this->validateData($request->all());
        // store something
        return redirect()->action('controller@index')->withMessage( 'Saved Successfully' );
    } catch ( ValidationException $e ) {
        return redirect()->action('controller@create')->withInput()->withErrors( $e->get_errors() );
    }
}
private function validateData($requestParams)
{
    // Your validation logic here
    $validator->validate( $requestParams );
}

您只是忘记在验证异常D之后'return',那么您就不必'exit;'