Reputation: 269
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
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
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
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