我希望能够在启动保存之前验证具有相关模型的创建表单。我正在保存一个拥有许多相关模型的组织。由于我有许多多对多的关系,我必须首先创建主要模型,然后经历一个费力的过程,从输入数据中单独创建每个相关的模型。在创建初始组织后,我在组织存储库中调用“createRelated”方法。
public function createRelated($input)
{
$this->orgtypes()->attach(1, ['objectstate_id' => ORGANIZATION_STARTED]);
$this->addresses()->create(array_only($input, ['street1', 'zip', 'city', 'state_code']));
for ($i=0; $i < 2; $i++)
{
if($input['phone_numbers_'.$i.'_number'])
{
$this->phoneNumbers()->create(['phone_number_type_id' => $input['phone_numbers_'.$i.'_phone_number_type_id'], 'number' => $input['phone_numbers_'.$i.'_number']]);
}
}
$this->procedures()->attach($input['procedures']);
$input['objectstate_id'] = USER_STARTED;
$input['password'] = $this->encryptPassword($input['password']);
$this->users()->create(array_only($input, ['first_name', 'last_name', 'email', 'password', 'objectstate_id']));
$this->profileElements()->create(['type' => 'short_description', 'content' => $input['short_description']]);
}
不得不调出每个输入并将其发送到适当的模型对我来说似乎不对,但这就是我在IRC上听到的“正确”方式。但现在我来验证,目前没有验证这些模型的创建,即使输入可能违反验证规则。令我感到惊讶的是,没有命名约定(我已经看到),它清楚地标识了相关的模型输入,因此可以在不进行上述手动处理的情况下对其进行验证和创建。在开始上述保存事务之前,有关如何验证相关输入数据的任何想法吗?
我的组织验证器如下:
<?php namespace Acme\Validators\Organizations;
use Acme\Validators\ValidatorAbstract;
class Validator extends ValidatorAbstract {
/**
* Validation rules
*/
protected $rules = array(
'organization_name' => 'required'
);
/**
* Custom Validation Messages
*/
protected $messages = array(
);
}
<?php namespace Acme\Validators;
use Illuminate\Support\MessageBag as MessageBag;
/*
* This class defines abstract Validator methods
*/
abstract class ValidatorAbstract implements ValidatorInterface {
protected $validator;
protected $input;
protected $errors;
/**
* @param array $input
*
*/
public function __construct($input = NULL, MessageBag $bag)
{
$this->input = $input ?: \Input::all();
$this->validator = \Validator::make($this->input, $this->rules, $this->messages);
$this->errors = $bag;
}
/**
* Run validation on input.
*
* @return boolean
*/
public function passes()
{
if($this->validator->passes())
{
return true;
}
$this->errors = $this->validator->messages();
return false;
}
/**
* Get all errors stored.
*
* @return MessageBag
*/
public function getErrors()
{
return $this->errors;
}
/**
* Add new error.
*
* @return MessageBag
*/
public function addError($key, $message)
{
return $this->errors->add($key, $message);
}
}
我的抽象存储库类,我引入了Ardent
<?php namespace Acme\Repositories;
// use Eloquent;
use LaravelBook\Ardent\Ardent;
/*
* This class defines Eloquent methods
*/
abstract class EloquentRepositoryAbstract extends Ardent implements RepositoryInterface {
protected $guarded = [];
public $timestamps = false;
public $autoHydrateEntityFromInput = true; // Ardent hydrates on new entries' validation
public $forceEntityHydrationFromInput = true; // Ardent hydrates whenever validation is called
…
我的控制器:
<?php
use \Acme\Repositories\Organizations\OrganizationRepositoryInterface;
use \Acme\Validators\Organizations\Validator;
use \Acme\Validators\Users\EditValidator as UsersValidator;
class OrganizationsController extends BaseController {
/**
* Organization Repository
*
* @var repository
* @var validator
* @var usersValidator
*/
protected $repository;
protected $validator;
protected $usersValidator;
public function __construct(OrganizationRepositoryInterface $repository,
Validator $validator,
UsersValidator $usersValidator)
{
$this->repository = $repository;
$this->validator = $validator;
$this->users_validator = $usersValidator;
}
[...] Vanilla雄辩的风格商店方法:
public function store()
{
$input = Input::all();
$opasses = $this->validator->passes();
$ppasses = $this->repository->validateProcedure($input);
$upasses = $this->users_validator->passes();
if($opasses && $ppasses['status'] && $upasses)
{
$new_organization = $this->repository->create(['organization_name' => $input['organization_name']]);
if($input['logo_url'])
{
$new_organization->processImage($input, Request::root());
}
if($new_organization->saveRelated($input, 'create'))
{
return Redirect::route('home')
->with('message', 'Organization Created.');
}
else
{
return Redirect::route('organizations.create')
->withInput()
->with('message', 'There were errors in the creation of this Organization');
}
}
return Redirect::route('organizations.create')
->withInput()
->withErrors(array_merge($this->validator->getErrors()->toArray(), $this->users_validator->getErrors()->toArray(), $ppasses))
->with('message', 'There were validation errors.');
}
这一切似乎过于复杂和脆弱。
答案 0 :(得分:0)
我认为最棘手的决定是在调用验证方法之前放置验证规则。这是一个有用的链接:http://laravel.com/docs/validation#available-validation-rules。
以下是我的做法,但我仍在决定将验证规则/错误消息放在何处。
Laravel 4的内置验证类有一种方法可以使验证变得简单:
Validator::make($input, $rules=array(), $errors=array())
(第三个参数是可选的)
在您的情况下,在调用create方法之前(假设用于保存元素),您可以这样做:
$rules = array(
"first_name" : "required",
"second_name" : "required",
and so on...
);
我给你的链接会给你可能的规则。最后,您还可以创建自己的自定义错误消息,如下所示:
$messages = array(
"required" => "This :attribute field is required"
and so on...
);
:属性将填写自动验证失败的字段。
然后,要验证您只是传入这些数组并调用pass()方法或fail()方法:
Validator::make($input, $rules, $messages)->passes()
(如果传递则返回true,如果失败则返回false)
我认为这样做会更加清晰:
$validation = Validator::make($input, $rules, $messages);
if ($validation->passes()) {
// save data
}
作为奖励,您可以访问此阵列中的错误消息:
$errors = $validation->messages();
所以,我希望能回答你的问题。我认为最大的问题是在哪里放置这些验证规则,因为我认为还没有一个约定。如果您有任何意见,请分享您的见解和意见。感谢。