Search code examples
laravellaravel-5laravel-validation

Laravel Array Validation Unique with an id


How can you use the unique validation rule when updating data with an id parameter so that the validation doesn't fail when just saving an existing value?

'columns.*.name' => 'required|unique:columns, name, id, columns.id'

id needs to be replaced with the value of * from the array but I can't figure out how.


Solution

  • I ended up implementing a more complex solution which I think covers all eventualities.

    I make a list of all current values for the given column from the database, including the limiting where clause (this should be optional but isn't at the moment).

    I then overwrite any values contained within the request.

    Finally I count the number of times each value is used in the request and check the current value isn't used more than once.

    This will potentially throw multiple validation failures for each duplicate value however I don't think this is an issue.

    <?php
    
    namespace App\Providers;
    
    use DB;
    use Validator;
    
    use Illuminate\Support\ServiceProvider;
    
    class ValidationServiceProvider extends ServiceProvider
    {
        /**
         * Bootstrap any application services.
         *
         * @return void
         */
        public function boot()
        {
    
            Validator::extend('array_unique', function($attribute, $value, $parameters, $validator) {
                $table = $parameters[0];
                $column = $parameters[1];
                $ref = $parameters[2];
                $id = $parameters[3];
    
                $values = DB::table($table)->where($ref, $id)->pluck($column, 'id');
    
                $attributes = explode(".", $attribute);
                $data = $validator->getData();
    
                $items = $data[$attributes[0]];
    
                foreach($items as $key => $item)
                {
                    $values[$key] = $item[$attributes[2]];
                }
    
                $counts = array_count_values($values);
    
                return $counts[$value] < 2;
            });
        }
    
        /**
         * Register the service provider.
         *
         * @return void
         */
        public function register()
        {
            //
        }
    }