2013-07-30 2 views
2

Я пытаюсь написать проверяемое приложение Laravel 4. В книге Тейлора Отуэллса о Laravel https://leanpub.com/laravel он пишет, что мы должны рассмотреть вопрос о создании класса UserValidator в пространстве имен Validation и вставить этот валидатор в ваш репозиторий. Не могли бы вы привести пример кода, который будет выглядеть в контроллере, хранилище и тестах. Если вход пользователя неудовлетворителен, следует ли исключить исключение проверки в репозитории и уловить ошибки в контроллере? http://jasonlewis.me/article/laravel-advanced-validationПроверка и проверки репозитория Laravel 4

+1

Обратите внимание, что [ссылка] (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, говорит о том, что вы выполняете валидацию _directly в model_ вместо использования репозитория. Поэтому я жестко считаю, что эта основа ответа на мой личный опыт может представлять интерес для ОП. –

3

Недавно я закодированы что-то похожее на это, которое было рекомендовано laracasts (http://laracasts.com) (который ссылается книга Taylor 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; 
    } 

} 

$ this-> validate мог бы использоваться так же легко, как и родительский :: проверять внутри класса.

Другой пример, поскольку laracasts предоставляет уроки, у них может быть файл LessonValidator.php, содержащий класс LessonValidator расширяет Validator {} с другим набором правил.

Использование в репозитории? Репозиторий интерфейс и поставщик услуг исключается

<?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 инкапсулирует набор объектов, хранящихся в хранилище данных, и выполняемые над ними операции, обеспечивая более объектно-ориентированное представление уровня персистентности. См. [Мартин Фаулер из каталога EAA] (http://martinfowler.com/eaaCatalog /repository.html) –

+0

Репозиторий не вызывает контроллер, он просто уведомляет слушателя о его результатах, который, случается, является контроллером. Мэтт Уинн продемонстрировал это на конференции Gotham Ruby, а Джеффри Уэй сделал свой перевод в Laravel в его экранизацию «Controller Cleanup». –

+0

Если Мэтт Уинн просто следил за тем, что «должно» сделать, он не застрял бы со своей идеей пассивного контролера. Ссылки: http://vimeo.com/44807822 - https://laracasts.com/lessons/controller-cleanup –

Смежные вопросы