Laravel 4: Unique Validation for Multiple Columns

2019-01-18 06:39发布

问题:

I know this question has been asked earlier but i did not get relevant answer.

I want to know that how can i write a rule to check uniqueness of two columns. I have tried to write a rule like:

public $rules = array(
    "event_id"=>"required",
    "label"=>"required|unique:tblSection,label,event_id,$this->event_id",
    "description"=>"required"
);

In my example i need to put validation so that one label could be unique for a single event id but may be used for other event id as well. For Example i want to achieve:

id   event_id    label   description
1     1          demo    testing
2     2          demo    testing

In the rule defined above, somehow i need to pass current selected event_id so that it could check whether the label does not exist in the database table for selected event_id but i am getting syntax error like:

{"error":{"type":"Symfony\\Component\\Debug\\Exception\\FatalErrorException","message":"syntax error, unexpected '\"'","file":"\/var\/www\/tamvote\/app\/modules\/sections\/models\/Sections.php","line":39}}

Note: I don't want to use any package but simply checking if laravel 4 capable enough to allow to write such rules.

回答1:

The answer from Mohamed Bouallegue is correct.

In your controller for the store method you do:

Model::$rules['label'] = 'required|unique:table_name,label,NULL,event_id,event_id,' .$data['event_id'];

where $data is your POST data.

And for the update method you do:

$model = Model::find($id);
Model::$rules['label'] = 'required|unique:table_name,label,NULL,event_id,event_id,'.$data['event_id'].',id,id'.$model->id;

where $data is your PUT/PATCH data, $model is the record you are editing and id is the table primary key.



回答2:

I didn't try this before but I think if you get the event_Id before validating then you can do it like this:

'label' => 'unique:table_name,label,NULL,event_id,event_id,'.$eventId
//you should get the $eventId first


回答3:

If you want to declare your validation rules statically you can do this as well. It's not the most efficient since it checks the database for each value.

protected $rules = [
    'user_id' => 'unique_multiple:memberships,user_id,group_id',
    'group_id' => 'unique_multiple:memberships,user_id,group_id',
]

/**
 * Validates that two or more fields are unique
 */
Validator::extend('unique_multiple', function ($attribute, $value, $parameters, $validator)
{
    //if this is for an update then don't validate
    //todo: this might be an issue if we allow people to "update" one of the columns..but currently these are getting set on create only
    if (isset($validator->getData()['id'])) return true;

    // Get table name from first parameter
    $table = array_shift($parameters);

    // Build the query
    $query = DB::table($table);

    // Add the field conditions
    foreach ($parameters as $i => $field){
        $query->where($field, $validator->getData()[$field]);
    }

    // Validation result will be false if any rows match the combination
    return ($query->count() == 0);

});


回答4:

Like Sabrina Leggett mentioned, you need to create your own custom validator.

Validator::extend('uniqueEventLabel', function ($attribute, $value, $parameters, $validator) {
    $count = DB::table('table_name')->where('event_id', $value)
                                    ->where('label', $parameters[0])
                                    ->count();

    return $count === 0;
}, 'Your error message if validation fails.');

You can call your validator by adding the following line to your rules:

'event_id' => "uniqueEventLabel:".request("label")

If you need more fields, you could add a new where clause to the sql statement.

(Source: edcs from this answer)



回答5:

As you I was looking for hours to do that but nothing worked, I test everything ... suddenly the randomness of the doc I came across this:

'email' => Rule::unique('users')->where(function ($query) {
              return $query->where('account_id', 1);
           })

https://laravel.com/docs/5.5/validation#rule-unique

and it works perfectly and moreover it is very flexible :)