2013-07-30 113 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 –