1

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.

3 Answers 3

1

You can use something like this

namespace App\Validations;

class ClientValidation
{

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public static function rules($client_id = "")
{
    return [
        'email'          => 'required|email|unique:shippers,email,'. $client_id,
        'first_name'     => 'required',
        'last_name'      => 'required',
        'company'        => 'required',
        'phone'          => 'required',
        'password'       => 'required',
    ];
}

/**
 * Get the specific message for rules that apply to the request.
 *
 * @return array of message
 */
public static function messages()
{
    return [
        //
    ];
}

}

This is my custom validations so you need to make folder and put this inside..

Sign up to request clarification or add additional context in comments.

Comments

0

Use the model id as the third parameter of the unique rule to skip the current record:

public function rules()
{
    $id = $this->route('model')->id;

    return [
        'columns.*.name' => "required|unique:columns,name,{$id}"
    ];
}

If you are using the same form request class when creating and updating a model, check if this is a patch request first:

$id = $this->method() == 'PATCH' ? $this->route('model')->id : null;

And if you're not using route model binding, replace 'model' with whatever you're passing to your route, instantiate the model and pass its id.

Comments

0

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()
    {
        //
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.