テスト可能な Laravel 4 アプリケーションを作成しようとしています。Laravel に関する Taylor Otwell の本https://leanpub.com/laravelで、Validation 名前空間内に UserValidator クラスを作成し、そのバリデーターをリポジトリに挿入することを検討する必要があると彼は書いています。コントローラー、リポジトリ、およびテストでのコードのコード例を提供してください。ユーザー入力が不十分な場合、リポジトリで検証例外をスローし、コントローラーでエラーをキャッチする必要がありますか? http://jasonlewis.me/article/laravel-advanced-validation
2 に答える
私は最近、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 は、クラス内で parent::validate と同じくらい簡単に使用できます。
別の例として、laracasts はレッスンを提供するため、異なるルール セットを持つクラス LessonValidator extends Validator {}を含む 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 の自動読み込み、依存関係の挿入、およびカスタム サービス プロバイダーの作成について調べました。
個人的には、モデルで直接検証を行うことを好みます。つまり、各モデルには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);
}
}