Laravel update model with unique validation rule for attribute

后端 未结 18 2117
春和景丽
春和景丽 2020-11-27 12:45

I have a laravel User model which has a unique validation rule on username and email. In my Repository, when I update the model, I rev

相关标签:
18条回答
  • 2020-11-27 13:12

    For anyone using a Form request

    In my case i tried all of the following none of them worked:

    $this->id, $this->user->id, $this->user.

    It was because i could not access the model $id nor the $id directly.

    So i got the $id from a query using the same unique field i am trying to validate:

        /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        $id = YourModel::where('unique_field',$this->request->get('unique_field'))->value('id');
        return [
            'unique_field' => ['rule1','rule2',Rule::unique('yourTable')->ignore($id)],
        ];
    }
    
    0 讨论(0)
  • 2020-11-27 13:13
    public static function custom_validation()
    {
        $rules = array('title' => 'required ','description'  => 'required','status' => 'required',);
        $messages = array('title.required' => 'The Title must be required','status.required' => 'The Status must be required','description.required' => 'The Description must be required',);
        $validation = Validator::make(Input::all(), $rules, $messages);
        return $validation;
    }
    
    0 讨论(0)
  • 2020-11-27 13:16

    Laravel 5.8 simple and easy

    you can do this all in a form request with quite nicely. . .

    first make a field by which you can pass the id (invisible) in the normal edit form. i.e.,

     <div class="form-group d-none">
          <input class="form-control" name="id" type="text" value="{{ $example->id }}" >
     </div>
    

    ... Then be sure to add the Rule class to your form request like so:

    use Illuminate\Validation\Rule;
    

    ... Add the Unique rule ignoring the current id like so:

    public function rules()
    {
        return [
              'example_field_1'  => ['required', Rule::unique('example_table')->ignore($this->id)],
              'example_field_2'  => 'required',
    
        ];
    

    ... Finally type hint the form request in the update method the same as you would the store method, like so:

     public function update(ExampleValidation $request, Examle $example)
    {
        $example->example_field_1 = $request->example_field_1;
        ...
        $example->save();
    
        $message = "The aircraft was successully updated";
    
    
        return  back()->with('status', $message);
    
    
    }
    

    This way you won't repeat code unnecessarily :-)

    0 讨论(0)
  • 2020-11-27 13:23

    Laravel 5 compatible and generic way:

    I just had the same problem and solved it in a generic way. If you create an item it uses the default rules, if you update an item it will check your rules for :unique and insert an exclude automatically (if needed).

    Create a BaseModel class and let all your models inherit from it:

    <?php namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class BaseModel extends Model {
    
        /**
         * The validation rules for this model
         *
         * @var array
         */
        protected static $rules = [];
    
        /**
         * Return model validation rules
         *
         * @return array
         */
        public static function getRules() {
            return static::$rules;
        }
    
        /**
         * Return model validation rules for an update
         * Add exception to :unique validations where necessary
         * That means: enforce unique if a unique field changed.
         * But relax unique if a unique field did not change
         *
         * @return array;
         */
        public function getUpdateRules() {
            $updateRules = [];
            foreach(self::getRules() as $field => $rule) {
                $newRule = [];
                // Split rule up into parts
                $ruleParts = explode('|',$rule);
                // Check each part for unique
                foreach($ruleParts as $part) {
                    if(strpos($part,'unique:') === 0) {
                        // Check if field was unchanged
                        if ( ! $this->isDirty($field)) {
                            // Field did not change, make exception for this model
                            $part = $part . ',' . $field . ',' . $this->getAttribute($field) . ',' . $field;
                        }
                    }
                    // All other go directly back to the newRule Array
                    $newRule[] = $part;
                }
                // Add newRule to updateRules
                $updateRules[$field] = join('|', $newRule);
    
            }
            return $updateRules;
        }
    }    
    

    You now define your rules in your model like you are used to:

    protected static $rules = [
        'name' => 'required|alpha|unique:roles',
        'displayName' => 'required|alpha_dash',
        'permissions' => 'array',
    ];
    

    And validate them in your Controller. If the model does not validate, it will automatically redirect back to the form with the corresponding validation errors. If no validation errors occurred it will continue to execute the code after it.

    public function postCreate(Request $request)
    {
        // Validate
        $this->validate($request, Role::getRules());
        // Validation successful -> create role
        Role::create($request->all());
        return redirect()->route('admin.role.index');
    }
    
    public function postEdit(Request $request, Role $role)
    {
        // Validate
        $this->validate($request, $role->getUpdateRules());
        // Validation successful -> update role
        $role->update($request->input());
        return redirect()->route('admin.role.index');
    }
    

    That's it! :) Note that on creation we call Role::getRules() and on edit we call $role->getUpdateRules().

    0 讨论(0)
  • 2020-11-27 13:27

    I had the same problem. What I've done: add in my view hidden field with id of a model and in validator check the unique, only if I've get some id from view.

    $this->validate(
            $request,
            [
                'index'       => implode('|', ['required', $request->input('id') ? '' : 'unique:members']),
                'name'        => 'required',
                'surname'     => 'required',
            ]
    );
    
    0 讨论(0)
  • 2020-11-27 13:31

    Another elegant way...

    In your model, create a static function:

    public static function rules ($id=0, $merge=[]) {
        return array_merge(
            [
                'username'  => 'required|min:3|max:12|unique:users,username' . ($id ? ",$id" : ''),
                'email'     => 'required|email|unique:member'. ($id ? ",id,$id" : ''),
                'firstname' => 'required|min:2',
                'lastname'  => 'required|min:2',
                ...
            ], 
            $merge);
    }
    

    Validation on create:

    $validator = Validator::make($input, User::rules());
    

    Validation on update:

    $validator = Validator::make($input, User::rules($id));
    

    Validation on update, with some additional rules:

    $extend_rules = [
        'password'       => 'required|min:6|same:password_again',
        'password_again' => 'required'
    ];
    $validator = Validator::make($input, User::rules($id, $extend_rules));
    

    Nice.

    0 讨论(0)
提交回复
热议问题