mozg
mozg

Reputation: 269

laravel 4.1 unique validation on update fails

Laravel 4.1. I want to update a city, check the rules and it fails on unique check.

Rules:

public static $rules = [
    'name' => 'required|alpha_dash|unique:cities',
    'slug' => 'alpha_dash|unique:cities',
    'seo_title' => 'required|max:60|unique:cities',
    'seo_description' => 'required|max:160|unique:cities',
    'rank' => 'integer',
    'visible' => 'integer'
];

I know, I can smth like:

'name' => 'required|alpha_dash|unique:cities, name, ##',

where ## - id, but I cant dynamically set id to updated one.

'name' => "required|alpha_dash|unique:cities, name, $id", // doesnt work
'name' => "required|alpha_dash|unique:cities, name, $this->id", // doesnt work

Is there any way to do it normally ?

Upvotes: 0

Views: 609

Answers (3)

ilumos
ilumos

Reputation: 362

I found an elegant-ish way to do this using fadion/ValidatorAssistant:

<?php

use Fadion\ValidatorAssistant\ValidatorAssistant;

class CityValidator extends ValidatorAssistant {

    // standard rules
    public static $rules = [
        'name' => 'required|alpha_dash',
        'slug' => 'alpha_dash',
        'seo_title' => 'required|max:60',
        'seo_description' => 'required|max:160',
    ];

    // some preparation before validation
    protected function before()
    {
        // Inject the given city id into the unique rules
        $this->rules['name'] .= 'unique:cities,name,' . $this->inputs['id'];
        $this->rules['slug'] .= 'unique:cities,slug,' . $this->inputs['id'];
        $this->rules['seo_title'] .= 'unique:cities,seo_title,' . $this->inputs['id'];
        $this->rules['seo_description'] .= 'unique:cities,seo_description,' . $this->inputs['id'];
    }

There's almost certainly a more elegant way to do this when you need several fields to be unique database-wide, but the above works very well for times when you only need one part to be unique.

Upvotes: 0

majidarif
majidarif

Reputation: 20105

The 3rd argument accepts a value to be ignored... If you want to do a WHERE clause, do it like:

'name' => array("required", "alpha_dash", "unique:cities,name,null,id,id,$this->id"...

The docs says:

Adding Additional Where Clauses

You may also specify more conditions that will be added as "where" clauses to the query:

'email' => 'unique:users,email_address,NULL,id,account_id,1'

In the rule above, only rows with an account_id of 1 would be included in the unique check.

Learn by example:

email => unique:users,email_address,id,NULL,field_1,value_1,field_2,value_2,field_x,value_x

Generates the query:

SELECT
    count(*) AS AGGREGATE
FROM
    `entries`
WHERE
    `email_address` = ?
AND `id` <> NULL
AND `field_1` = `value_1`
AND `field_2` = `value_2`
AND `field_x` = `value_x`

Upvotes: 0

Paul Bele
Paul Bele

Reputation: 1534

You can do it in separate ways.

An easy way is to use different rules based on different actions . When you will create the model, you will use the rules that you currently have.

When you will update the model, you will change the unique:cities to exists:cities

I usually do this with a validation service.

You create a base abstract Validator in services/ , which has a passes() function.

For each model, you create a ModelValidator , in your case CityValidator. Where you put your rules like :

public static $rules = [
    'new'=>[
    'name' => 'required|alpha_dash|unique:cities',
    'slug' => 'alpha_dash|unique:cities',
    'seo_title' => 'required|max:60|unique:cities',
    'seo_description' => 'required|max:160|unique:cities',
    'rank' => 'integer',
    'visible' => 'integer'],

    'edit'=>[
    'name' => 'required|alpha_dash|exists:cities',
    'slug' => 'alpha_dash|unique:cities',
    'seo_title' => 'required|max:60|exists:cities',
    'seo_description' => 'required|max:160|exists:cities',
    'rank' => 'integer',
    'visible' => 'integer'
    ]
];

Upvotes: 1

Related Questions