2013-07-30 65 views
2

我正在尝试编写一个可测试的Laravel 4应用程序。在Taylor Otwells关于Laravel https://leanpub.com/laravel的书中,他写道我们应该考虑在Validation命名空间内创建一个UserValidator类,并将该验证器注入到存储库中。您能否提供代码的代码示例在控制器,存储库和测试中看起来像?如果用户输入不满意,我应该在存储库中引发一个验证异常并捕获控制器中的错误? http://jasonlewis.me/article/laravel-advanced-validationLaravel 4知识库验证和测试

+1

请注意,最后提供的[link](http://jasonlewis.me/article/laravel-advanced-validation)与Laravel 3相关,而不是Laravel 4. –

回答

1

个人而言,我更愿意直接在模型中进行验证。这就是说,我会为每个模型getValidator()方法如下:

class User extends Eloquent 
{ 
    public function getValidator() 
    { 
     $params = array(
      'username' => $this->username, 
      'password' => $this->password, 
     ); 

     $rules = array(
      'username' => ['required', 'unique:users'], 
      'password' => ['required', 'min:6'], 
     ); 

     return Validator::make($params, $rules); 
    } 
} 

然后在我的控制器,命令或测试我只是调用这个方法有一个验证器实例,然后我会叫我所需要的方法,那可能是passes()fails()

下面举例说明我如何在控制器中实际使用它。

class UserController extends BaseController 
{ 
    public function processCreateUser() 
    { 
     // Retrieve user input. 
     $user = new User(Input::all()); 

     // Validate input. 
     $validator = $user->getValidator(); 

     if ($validator->passes()) 
     { 
      // Hash the password. 
      $user->password = Hash::make($user->password); 

      // Save the new user. 
      $user->save(); 

      return Redirect::to('users') 
       ->with('success', 'User created!'); 
     } 

     return Redirect::route('users.create') 
      ->withInput() 
      ->with('error', 'Cannot create user, please double check the form.') 
      ->withErrors($validator); 
    } 
} 
+2

绝不会有这个答案,涉及到任何原始问题的要求! – JasonMortonNZ

+0

@JasonMortonNZ,我同意你的意见。但OP提供的最后一个链接是关于在model_中直接实现验证,而不是使用存储库。所以我很难说,基于我个人经验的这个答案可能会对OP产生兴趣。 –

3

我最近编码与此类似,这是建议laracasts(http://laracasts.com)(其中引用的泰勒Otwell的书)。请注意,您不必遵循所使用的应用程序结构。

<?php namespace ACME\Services\Validation; 

use Validator as V; 

abstract class Validator { 

    protected $errormessages; 
    protected $rules; 

    public function validate($input, $rules) 
    { 

     $validator = V::make($input, $rules); 
     $this->rules = $rules; 

     if ($validator->fails()) { 

      $this->errormessages = $validator->messages(); 

      return false; 
     } 

     return true; 

    } 

    public function getErrorMessages() 
    { 
     return $this->errormessages; 
    } 

    public function getValidationRules() 
    { 
     return $this->rules; 
    } 
} 

这是为了各种验证目的而应该扩展的类,如下面的示例代码片段所示。

<?php namespace ACME\Services\Validation; 

use Auth; 

class UserValidator extends Validator { 

    protected $create_rules = [ 
     'firstname' => 'required|min:3|max:64|alpha-dash', 
     'lastname' => 'required|min:2|max:64|alpha-dash', 
     'account' => 'required|min:4|max:15|alpha_num', 
     'email' => 'required|between:3,254|email|unique:users', 
     'description' => 'max:500' 
    ]; 

    protected $edit_rules = [ 
     'firstname' => 'required|min:3|max:64|alpha-dash', 
     'lastname' => 'required|min:2|max:64|alpha-dash', 
     'description' => 'max:500' 
    ]; 

    protected $pass_edit_rules = [ 
     'oldpassword' => 'required', 
     'password' => 'required|min:5|confirmed', 
     'password_confirmation'=> 'required|min:5' 
    ]; 

    public function validateCreate($input) 
    { 


     return parent::validate($input, $this->create_rules); 
    } 

    public function validateEdit($input) 
    { 
     $newRules = $this->edit_rules; 

     if ($this->validatePasswordChanged($input)) 
      $newRules = array_merge($newRules, $this->pass_edit_rules); 

     return parent::validate($input, $newRules); 
    } 

    public function validatePasswordChanged($input) 
    { 
     return $input['password'] != '' || $input['oldpassword'] != '' || $input['password_confirmation'] != '' ? true : false; 
    } 

} 

$这个 - >验证本来是很容易使用父::类中进行验证。

另一个例子中,由于提供了laracasts教训,它们可以具有一个包含类LessonValidator一个LessonValidator.php文件延伸验证{}具有不同的一组规则。

在存储库中使用? 的仓库接口和服务供应商被排除在外

<?php namespace ACME\Repositories; 

use User; 
use UserController; 
use ACME\Services\Validation\UserValidator; 

class DatabaseUserRepository extendes UserRepositoryInterface { 
    protected $validator; 

    public function __construct(UserValidator $validator, UserController $listener) 
    { 
     $this->validator = $validator; 
     $this->listener = $listener; 
    } 

    public function createUser(User $user) 
    { 
     if ($this->validator->validateCreate($input)) 
      return $this->listener->withErrors('/',$this->validator->getErrorMessages()); 

     /* Validation passed, create user with User::create() */ 

     $this->listener->withView('usercreatedview'); 
    } 
} 

你的控制器将随后包含沿着线的东西。

<?php 

use ACME\Repositories\UserRepositoryInterface; 

class UserController extends BaseController { 

    protected $repository; 

    public function __construct(UserRepositoryInterface $repository) 
    { 
     $this->repository = $repository; 
    } 

    public function withErrors($path, MessageBag $errors) 
    { 
     return Redirect::to($path)->withErrors($errors); 
    } 

    public function withView($view) 
    { 
     return View::make($view); 
    } 

    /* Other controller stuff... */ 
} 

请注意,这会报错了,如果你不DatabaseUserRepository结合UserRepositoryInterface(我可以作出任何错别字)。您可以将验证类注入控制器,但我相信您想要合并存储库。我倾向于在事件处理程序中执行验证和存储库调用。

我会阅读psr自动加载,依赖注入和创建自定义服务提供者。

+1

控制器应该调用存储库,而不是其他方式。 _Repository封装了保存在数据存储中的一组对象以及对它们执行的操作,提供了一个更加面向对象的持久层视图._请参阅[Martin Fowler的EAA目录P](http://martinfowler.com/eaaCatalog /repository.html) –

+0

存储库不会调用控制器,它只是将侦听器的结果通知给控制器。 Matt Wynne在Gotham Ruby会议上展示了它,Jeffrey Way在他的“控制器清理”屏幕演示中对Laravel做了一些翻译。 –

+0

如果Matt Wynne简单地遵循了“应该”做的事情,他就不会被他的被动控制器想法所困住。参考:http://vimeo.com/44807822 - https://laracasts.com/lessons/controller-cleanup –