【问题标题】:Laravel 4 ValidationLaravel 4 验证
【发布时间】:2013-05-07 05:23:18
【问题描述】:

我在创建新用户时使用以下规则进行验证:

protected $rules= [
    'name'    => 'required',
    'email'    => [
        'required',
        'unique:user',
        'email'
    ]
];

更新现有用户时,我使用与上图相同的规则集 但如果用户根本没有更改他的电子邮件,则不希望出现验证错误。

我目前使用以下方法解决此问题:

if (!User::changed('email')) {
    unset($user->email);
}

对我来说,这感觉像是一种肮脏的解决方法,所以我想知道是否有更好的选择。

还要注意changed 方法是我自己编写的。有谁知道有没有 是 Laravel 4 的原生方法,用于检查模型属性是否已更改?

谢谢!

【问题讨论】:

标签: php validation laravel laravel-4 eloquent


【解决方案1】:

唯一的验证规则允许忽略给定的 ID,在您的情况下是您正在更新的数据集的 ID。

'email' => 'unique:users,email_address,10'

http://four.laravel.com/docs/validation#rule-unique

【讨论】:

  • 顺便说一句,我通过在我的验证规则中使用占位符 :id: 来解决这个问题,然后在验证之前处理规则:github.com/betawax/role-model/blob/master/src/Betawax/RoleModel/…
  • 我喜欢使用占位符的想法,但我并不真正相信您的方法。对我关于更改状态的“第二个”问题有任何想法吗?我在 Laravel 3 的源代码中找到了一些关于更改方法的参考资料,但到目前为止在 Laravel 4 中还没有找到它
  • 在我的代码示例中,我将占位符替换为$this->getKey(),它可用于新的现有数据集。因此,您不必关心是创建新模型还是更新现有模型。只需在每个保存事件上替换占位符即可。您可以通过覆盖 Eloquent 的 save() 方法或使用 model events 来做到这一点。
  • 附录:我认为您可以使用 Eloquent 的 mutators (setter) 来检查您的模型属性是否已更改。 four.laravel.com/docs/eloquent#accessors-and-mutators
  • 您能否对 mutators 主题更具体一点?我想不出一种将它们实现为全局 propertyIsChanged 类型的方法的方法。
【解决方案2】:

一种方法是在模型中创建一个验证函数,并在控制器中调用它并传入输入、场景和 id(忽略)。

public function validate($input, $scenario, $id = null)
{
    $rules = [];

    switch($scenario)
    {
        case 'store':
            $rules   = [
                'name'     => 'required|min:5|unique:users',
                'email'    => 'required|email|unique:users',
                'password' => 'required|min:4|confirmed'
            ];
            break;

        case 'update';
            $rules   = [
                'name'     => 'required|min:5|unique:users' .',name,' . $id,
                'email'    => 'required|email|unique:users' .',email,' . $id,
                'password' => 'min:4|confirmed'
            ];
            break;
    }

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

然后在控制器中:

    $input      = Input::all();
    $validation = $user->validate($input, 'update', $user->id);

    if ($validation->fails())
    {
        // Do stuff
    }
    else
    {
        // Validation passes
        // Do other stuff
    }

正如其他人提到的,唯一规则的第三个参数指定要忽略的 id。您可以添加其他情况,例如“登录”以重复使用验证功能。

另外,Tuts Premium has a great series of lessons in "What's New In Laravel 4" 的 Jeffrey Way 包括其他几种使用服务和侦听器处理验证的方法。

【讨论】:

  • 向模型添加验证规则似乎是正确的解决方案。恕我直言,每次都为存储或更新添加参数很脏。这篇文章遵循了类似的解决方案forums.laravel.io/viewtopic.php?id=12104 也许这对某人有帮助。
【解决方案3】:

请参阅http://four.laravel.com/docs/validation#rule-unique 上的文档

你可以排除用户自己的id

protected $rules= [
    'name'    => 'required',
    'email'    => [
        'required',
        'unique:user,email,THE_USERS_USER_ID',
        'email'
    ]
];

【讨论】:

  • 我知道 exclude 参数,但我看不到将其注入我的规则集的有效非黑客方式,因此问题。
  • 你为什么认为这是骇人听闻的?
【解决方案4】:

截至 2014-01-14,您可以使用 sometimes 属性,我相信 Taylor 在 2 天前将它们添加到 Laravel 4.1

$v = Validator::make($data, array(
    'email' => 'sometimes|required|email',
));

sometimes 仅在输入存在时验证输入。如果您没有插入的默认值,这可能适合您的确切情况,也可能不适合。

http://laravel.com/docs/validation#conditionally-adding-rules

【讨论】:

    【解决方案5】:

    我在验证器函数中处理这类事情。我的验证器数组设置为类变量。然后我做这样的事情:

    public function validate() 
    {
        //exclude the current user id from 'unqiue' validators
        if( $this->id > 0 )
        {
            $usernameUnique = 'unique:users,username,'.$this->id;
            $emailUnique = 'unique:users,email,'.$this->id;
            $apiUnique = 'unique:users,api_key,'.$this->id;
        }
        else
        {
            $usernameUnique = 'unique:users,username';
            $emailUnique = 'unique:users,email';
            $apiUnique = 'unique:users,api_key';
        }
    
        $this->validators['username'] = array('required', 'max:32', $usernameUnique);
        $this->validators['email'] = array('required', 'max:32', $emailUnique);
        $this->validators['api_key'] = array('required', 'max:32', $apiUnique);
    
        $val = Validator::make($this->attributes, $this->validators);
    
        if ($val->fails())
        {
            throw new ValidationException($val);
        }
    }
    

    【讨论】:

      【解决方案6】:

      我已经通过对需要这样做的模型(例如用户)设置不同的更新和创建规则来解决这个问题。

      我有一个扩展 Eloquent 的模型类,我在其中定义验证,然后扩展模型的所有子模型都可以同时具有 $rules$update_rules 定义。如果您只定义 $rules,它将同时用于创建和更新。

      class Model extends Eloquent {
          protected $errors;
          protected static $rules = array();    
          protected $validator;
      
          public function __construct(array $attributes = array(), Validator $validator = null) {
              parent::__construct($attributes);    
              $this->validator = $validator ?: \App::make('validator');
          }
      
          protected static function boot() {
              parent::boot();
      
              # call validatie when createing
              static::creating(function($model) {
                  return $model->validate();
              });
      
              # call validatie when updating with $is_update = true param
              static::updating(function($model) {
                  return $model->validate(true);
              });
          }
      
          public function validate($is_update = false) {
              # if we have $update_rules defined in the child model, and save is an update
              if ($is_update and isset(static::$update_rules)) {
                  $v = $this->validator->make($this->attributes, static::$update_rules);
              }
              else {
                  $v = $this->validator->make($this->attributes, static::$rules);
              }
      
              if ($v->passes()) {
                  return true;
              }
      
              $this->setErrors($v->messages());
              return false;
          }
      
          protected function setErrors($errors) {
              $this->errors = $errors;
          }
      
          public function getErrors() {
              return $this->errors;
          }
      
          public function hasErrors() {
              return ! empty($this->errors);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2014-03-09
        • 2013-09-09
        • 2015-06-28
        • 1970-01-01
        • 2023-03-27
        • 2014-02-26
        • 2013-08-05
        • 2013-12-25
        • 2014-10-09
        相关资源
        最近更新 更多