Below is the structure of my table:
corporations
id
uuid
corporation_name
corp_branches
id
corp_id
branch_name
The relationship is defined as Each corporations can have Many corp_branches but I want to have a check that branch_name under each corporations should be unique. Two different branches under different corporations can have the same name but two branches under one corporation cant have the same name.
I have tried this
'branch_name' => 'required|string|max:100|unique:corp_branches,branch_name,NULL,id,corp_id,'.$this->get('corp_id'),
'branch_name' =>['required', 'unique:corp_branches,corp_id,'.$this->id.',NULL,corp_id,branch_name,'.$request->input('branch_name')]
You need Custom Validation Rules.
Step #1 - Generate a rule
php artisan make:rule UniqueBranch
Step #2 - Modify app/Rules/UniqueBranch.php
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class UniqueBranch implements Rule
{
protected $corp_id;
/**
* Create a new rule instance.
*
* #return void
*/
public function __construct($corp_id)
{
$this->corp_id = $corp_id;
}
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
// Assume your model name is `Corporation`
$corporation = Corporation::find($this->corp_id);
if ($corporation) {
$exists = $corporation
->corp_branches() // assume you have relation to braches
->where('name', $value)
->count();
if (!$exists) {
return true;
}
}
return false;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The branch name has already been taken.';
}
}
Step #3 - Using UniqueBranch
'branch_name' => [
'required',
'string',
'max:100',
new UniqueBranch($this->get('corp_id'))
]
PHP defines the relative formats and Laravel doesn't seen to have an available validation rule for that. For example:
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'created-at-from' => 'relative_format',
'created-at-until' => 'nullable|relative_format|gte:created-at-from'
];
}
How can we validate those formats?
UPDATE
What I'm using now:
Create a rule class.
php artisan make:rule RelativeFormat
Put the logic.
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
return (bool) strtotime($value);
}
And validates:
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'created-at-from' => [new RelativeFormat],
'created-at-until' => ['nullable', new RelativeFormat]
];
}
You can just create your own validation rule:
Validator::extend('relative_format', function($attribute, $value, $parameters)
{
return (bool) strtotime($value);
});
And add it to your AppServiceProvider.
I'm working with Laravel 5.5 and I'm trying to do some complex field validations and I don't seem to be able to find a solution for this.
I have three fields:
field_a (Boolean)
field_b (String)
field_c (String)
I need to validate that if field_a is true then field_b OR field_c are not empty.
I've tried to do something like:
'field_b' => 'required_with:field_a|required_if:field_c,',
'field_c' => 'required_with:field_a|required_if:field_b,',
But this way makes both fields required if field_a has been passed to the request.
Thank you in advance for your help.
I haven't been able to use Laravel's built-in validation system to do this kind of validation so I have created my own custom rule. I leave it here just in case somebody finds it useful.
class IfXOR implements Rule {
private $required;
private $fields;
/**
* Create a new rule instance.
*
* #param bool $required
* #param mixed $fields
* #return void
*/
public function __construct($required, $fields) {
$this->required = $required;
$this->fields = $fields;
}
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value) {
if(!$this->required) return true;
if(!is_array($this->fields)) return $value || !empty($this->fields);
return $value || !empty(array_filter(function($f) { return !empty($f); }, $this->fields));
}
/**
* Get the validation error message.
*
* #return string
*/
public function message() {
return 'The validation error message.';
}
}
Is it possible to use my custom validation rule in a validation request file?
i want to use my custom rule called EmployeeMail
here is the code of the request file
class CoachRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$rules = [];
if ($this->isMethod('post') ) {
$rules = [
'name' => 'required|string',
'email' => 'required|email|employeemail', <<<--- this
'till' => 'required|date_format:H:i|after:from',
];
}
//TODO fix this
//TODO add custom messages for every field
return $rules;
}
}
it gives me an error when i try to use it like this
Method [validateEmployeemail] does not exist.
code of custom rule
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class EmployeeMail implements Rule
{
/**
* Create a new rule instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
// If mail is that of an employee and not a student pass it
return preg_match("/#test.nl$/", $value) === 1;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'Email is geen werknemers mail';
}
}
can i only use this custom rule like this?
$items = $request->validate([
'name' => [new FiveCharacters],
]);
Rutvij Kothari answered the question in the comments.
It seems you are validating string with a regular expression, the same logic can be achieved by regex buit-in validation method. Check it out. laravel.com/docs/5.5/validation#rule-regex No need to create your own validation rule. – Rutvij Kothari
If you want to use your validation pass it into an array. like this. 'email' => ['required', 'email', new employeemail]
How can I have a unique validation rule on 2 fields?
a. The application should not allow two people to have the same identical first name and last name.
It is allowed that the users fills in only a first name or only a last name. Because the user may have only one of them.
b. But if the user enters only a first name (Glen), no other person in the table should have the same (first name = 'Glen' and last name = null). another 'Glen Smith' ok.
I tried the following rule. It works great when both fields (first and last name) are not null:
'firstName' => 'unique:people,firstName,NULL,id,lastName,' . $request->lastName
This rule fails on b. when only one field is present.
Any hint?
The built in unique validator wouldn't really support what you're trying to do. It's purpose is to ensure that a single valid is unique in the database, rather than a composite of two values. However, you can create a custom validator:
Validator::extend('uniqueFirstAndLastName', function ($attribute, $value, $parameters, $validator) {
$count = DB::table('people')->where('firstName', $value)
->where('lastName', $parameters[0])
->count();
return $count === 0;
});
You could then access this new rule with:
'firstName' => "uniqueFirstAndLastName:{$request->lastName}"
You'll probably find you might need to tweak your database query a little bit as it's untested.
I think you are looking for something like that:
'unique:table_name,column1,null,null,column2,'.$request->column2.',column3,check3'
This is an extensive answer to this question and how to create Laravel custom validator generally, you can simply copy and paste, and try to understand later:
Step 1: Create a provider app/Providers/CustomValidatorProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator as ValidatorFacade;
/**
* Provider for custom validators. Handles registration for custom validators.
*
*/
class CustomValidatorProvider extends ServiceProvider {
/**
* An array of fully qualified class names of the custom validators to be
* registered.
*
* #var array
*/
protected $validators = [
\App\Validators\MultipleUniqueValidator::class,
];
/**
* Bootstrap the application services.
*
* #return void
* #throws \Exception
*/
public function boot() {
//register custom validators
foreach ($this->validators as $class) {
$customValidator = new $class();
ValidatorFacade::extend($customValidator->getName(), function() use ($customValidator) {
//set custom error messages on the validator
func_get_args()[3]->setCustomMessages($customValidator->getCustomErrorMessages());
return call_user_func_array([$customValidator, "validate"], func_get_args());
});
ValidatorFacade::replacer($customValidator->getName(), function() use ($customValidator) {
return call_user_func_array([$customValidator, "replacer"], func_get_args());
});
}
}
/**
* Register the application services.
*
* #return void
*/
public function register() {
//
}
}
Step 2: Update your app.php in your config folder config/app.php to include your created provider in the provider array
App\Providers\CustomValidatorProvider::class,
Step 3: Create your custom validator, in my case, I am creating multiple unique fields validator app/Validators/MultipleUniqueValidator.php
<?php
namespace App\Validators;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Illuminate\Validation\Validator;
/**
* Multiple field uniqueness in laravel
*/
class MultipleUniqueValidator{
/**
* Name of the validator.
*
* #var string
*/
protected $name = "multiple_unique";
/**
* Return the name of the validator. This is the name that is used to specify
* that this validator be used.
*
* #return string name of the validator
*/
public function getName(): string {
return $this->name;
}
/**
*
* #param string $message
* #param string $attribute
* #param string $rule
* #param array $parameters
* #return string
*/
public function replacer(string $message, string $attribute, string $rule, array $parameters): string {
unset($parameters[0]);
$replacement = implode(", ", $parameters);
$replacement = str_replace("_", " ", $replacement);
$replacement = Str::replaceLast(", ", " & ", $replacement);
$replacement = Str::title($replacement);
return str_replace(":fields", "$replacement", $message);
}
/**
*
* #param string $attribute
* #param mixed $value
* #param array $parameters
* #param Validator $validator
* #return bool
* #throws \Exception
*/
public function validate(string $attribute, $value, array $parameters, Validator $validator): bool {
$model = new $parameters[0];
if (!$model instanceof Model) {
throw new \Exception($parameters[0] . " is not an Eloquent model");
}
unset($parameters[0]);
$this->fields = $parameters;
$query = $model->query();
$request = app("request");
foreach($parameters as $parameter){
$query->where($parameter, $request->get($parameter));
}
return $query->count() == 0;
}
/**
* Custom error messages
*
* #return array
*/
public function getCustomErrorMessages(): array {
return [
$this->getName() => ":fields fields should be unique"
];
}
}
Now you can do this in your request
'ANY_FIELD_CAN_CARRY_IT' => 'required|numeric|multiple_unique:'.YOUR_MODEL_HERE::class.',FIELD_1,FIELD_2,FIELD_3...',
Laravel now allows you to add where clauses into the unique rule.
In your case you could do something like this:
'firstName' => [
Rule::unique('people', 'firstName')->where(function ($query) use ($lastName) {
return $query->where('lastName', $lastName);
})
],
in my case this works just fine (in controller):
$request->validate([
'firstName' => 'required|min:3|max:255|unique:people,firstName,NULL,id,lastname,' . $request->input('lastname'),
], [
'unique' => 'Some message for "unique" error',
]);
You can do it if the Validator class isn't required for you:
if(Model::query()->where([
'column_1' => 'data_1',
'column_2' => 'data_2'
])->exists())
{
// some code..
}