Laravel:从私有方法重定向并传递错误信息

5
我有以下代码:
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语句。必须有一种方法可以在没有它的情况下使用闪存消息进行重定向。


解决方案应该放在Hieu Le的答案中,而不是问题中。请记住,这是一个“问与答”网站。 - John Saunders
3个回答

6

简而言之

更新您的私有方法代码,如下所示,使重定向与$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();
    }
}

解释

如果在控制器中间退出,有一些在应用程序终止时执行的工作将不再执行。 在您的情况下,Session中间件的terminate方法将不会被调用。 让我们看看它的内容(参考):

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

现在,看一下我们 Session 驱动的 save 方法 (参考链接)

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

如您所见,只有在Session中间件成功终止时才会保存闪存数据。使用旧代码时,闪存数据将丢失!

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


好的,我稍后会尝试这个。我现在在午餐时间。看起来很合理。 - pascalvgemert

0

我认为在那里使用if语句没有任何问题。基本上,您不会停止代码执行,这就是为什么即使验证失败,存储函数也会被执行的原因。重定向函数只是发送一个带有重定向位置的标头,它不会中止之后要执行的代码。它与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 );
}

如果你在私有函数中再次调用私有函数,情况会变得很糟糕。你需要在每个函数中都加上if语句,这样就会出现if语句链。 - pascalvgemert

-1

你只是忘记在验证异常后面加上'return',这样你就不必使用 'exit;'了:D。


然后它仍然执行“//存储某些内容” - pascalvgemert
我猜可能是因为您正在重定向到错误的操作(需要POST请求的操作)。也许'controller@create'是负责处理POST数据的方法? - naneri
没有问题。返回语句只会执行 // store something - pascalvgemert
哦,我明白了 - 我完全误解了你,罚分是应该的 :D。实际上,我不知道如何避免使用 'If' 语句。您可以检查所有流行的 Laravel 代码库 - 它们都坚持使用 'if' 语句来检查验证。这里有一个例子 https://github.com/LaravelIO/laravel.io/blob/master/app/controllers/ArticlesController.php - naneri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接