Laravel重定向和验证逻辑

时间:2015-01-03 12:12:19

标签: php redirect laravel exception-handling

我正在使用Laravel 4,我正在寻找在我的控制器方法中处理验证错误的优雅方法。下面代码中的所有内容都可以正常工作(在我实际验证的实际代码中。我的示例只是抛出异常来模拟失败的验证。)基本上,我想从每个控制器中获取try / catch块并将其放在另一个方法中所以我不会重复很多非常相似的代码。我的代码如下:

routes.php文件

Route::resource( 'foo', 'FooController', array('only' => array('create', 'store')));

FooController.php

class FooController extends \BaseController {

    public function create()
    {
        return View::make('foo');
    }

    public function store(){

        try {
            // Validation service call goes here.  We'll just force an exception
            throw new Exception('Invalid email address!');
        } catch (Exception $e) {    
            return Redirect::back()->withErrors($e->getMessage());
        }

        // Everything validated so lets save the data   
    }
}

foo.blade.php

<html>
<body>
    <h4>Welcome to page Foo!</h4>

    @if($errors->any())
    <h4>{{$errors->first()}}</h4>
    @endif

    {{ Form::open(array('url' => '/foo')) }}

        {{ Form::label('email', 'E-Mail Address') }}
        {{ Form::text('email', 'example@gmail.com') }}

        {{ Form::submit('Submit') }}
    {{ Form::close() }}
</body>
</html>

上面的代码工作正常。抛出了验证异常,我们被重定向回页面并显示错误消息。

我想要做的是将整个try / catch块移动到一个方法中,以清除store()方法中的混乱。像这样:

class FooController extends \BaseController {

    public function create()
    {
        return View::make('foo');
    }

    public function store(){

        $this->validateMe();

        // Everything validated so lets save the data   
    }

    public function validateMe()
    {
        try {
            // Validation service call goes here.  We'll just force an exception to
            // simulate invalid data the sake of the example
            throw new Exception('Invalid email address!');
        } catch (Exception $e) {    
            return Redirect::back()->withErrors($e->getMessage());
        }
    }
}

这个实现只是给我一个空白屏幕,因为重定向没有回到Laravel。重定向回表单的唯一方法是执行类似下面的操作。但是,这是行不通的,因为我永远无法达到实际保存数据的逻辑。

public function store(){

    return $this->validateMe();

    // Everything validated so lets save the data but we can 
    // never get here because of the return above.  This is bad!    
}

3 个答案:

答案 0 :(得分:2)

现在你的代码出了什么问题:你添加了:

public function store(){

return $this->validateMe();

// Everything validated so lets save the data   
}

所以你总是从这个函数返回,你的代码不会超出return语句。

我建议在Model类中进行验证/存储,这样你的控制器中的代码就更少了,而且修改起来也更容易。我制作了自己的模型,但您可以使用现有的包,例如: Laravel-Model-Validation


修改

我仍然不知道为什么你要在验证时抛出异常,如果有一个字段无效,如果名称,电子邮件,你只能抛出一个异常怎么办...

但如果你坚持,只需返回一系列你需要的东西

        } catch (Exception $e) {    
        return ['status' => 'failed',
               'validation_object' => $validator,
               'exception' => $e,
        ];
    } 
    //outside of catch, no exceptions occurred,
    return ['status' => 'success'];

然后在您的控制器中

public function store(){

$result = $this->validateMe();
if($result['status'] == 'success') {
    //code to save in db

    return Redirect::back()->with('message', 'saved');
}
else {
   return Redirect::back()->withErrors($result['exception']->getMessage());
}

答案 1 :(得分:1)

试试这个

 $inputs = Input::all();

$validator = Validator::make(
array(
    'field_name' => $inputs['field_name'],
    'field_name' => $inputs['field_name']
),
array(
    'field_name' => 'required',
    'field_name' => 'required|numeric'
)
);


if ($validator->fails())
            {
                return Redirect::back()->withInput()->withErrors($validator);
            }
            else
            {}

答案 2 :(得分:1)

我认为你要做的事实上是模仿Laravel 5控制器中的$this->validate()方法。我认为这里发生的事情的要点是为自定义异常定义global error handler,他们恰好称之为HttpResponseException

默认控制器有一个 trait (基本上是部分类实现),它定义了一个名为validate() here的方法,子控制器可以调用该方法进行验证。如果需要,您还可以使用 trait ,或者只需将必要的逻辑添加到基本控制器。几乎每个典型应用程序中的控制器都需要相同的东西。

当验证未通过时,该方法抛出上述异常here。 我看到这个自定义异常的主要原因是,您可以捕获有关当前请求的大量信息,当您在全局级别捕获异常时,您需要这些信息。他们只是构造一个重定向响应并将其保存在HttpResponseException实例中。

docs中所述,您需要做的就是编写一个错误处理程序来捕获该特定异常并返回捆绑到异常中的RedirectResponse。使用Response几乎就像它直接从控制器方法返回一样。当然你可以在这里放置各种其他逻辑来创建一些其他类型的响应来返回。

我相信Laravel 5他们在路由代码中执行上述here。通过错误处理程序方法意味着你会在它冒出更多级别之后捕获异常,但效果是相同的。

我知道这个答案在代码上很少,但我认为Laravel 5代码库比我能想到的任何东西都要强大得多,Laravel 4.2似乎已经提供了你需要的工具。复制那个。