Laravel validate unique if id is the same - php

I have a table/model that contains multiple albums per user.
Is there a way to say that the column title should be unique, but only for the rows that have the same user_id?
Example: http://pastebin.com/8dvM4a1T
As you can see in the example, the user with the id of 2 has created 2 albums, with the same title. I don't want that to be allowed, that's why I'm wondering if there's a way to deny that with the validator from Laravel?
I tried this, but that did not work.
// Validator
$validator = Validator::make($input, [
'title' => 'required|min:1|max:255|unique:galleries,title,'. Auth::user() -> id .',user_id',
'description' => 'min:1|max:255'
]);
Any help appreciated, thanks.

Your code should be something like:
'title' => 'unique:galleries,title,NULL,id,user_id,'.Auth::user() -> id.'',
Or, you can write a custom rule
Reference here

The approach with the default unique rule does not work because the rule expects the column value to be passed as the third parameter, so in your case it would check if the title column is equal to the Auth::user()->id value which is not what you want.
You can create you own custom validation rule by adding the following code to the boot method of the App\Providers\AppServiceProvider class:
Validator::extend('unique_custom', function ($attribute, $value, $parameters)
{
// Get the parameters passed to the rule
list($table, $field, $field2, $field2Value) = $parameters;
// Check the table and return true only if there are no entries matching
// both the first field name and the user input value as well as
// the second field name and the second field value
return DB::table($table)->where($field, $value)->where($field2, $field2Value)->count() == 0;
});
Now you can use the unique_custom (or you can name it whatever you like) rule like so:
$validator = Validator::make($input, [
'title' => 'required|min:1|max:255|unique_custom:galleries,title,user_id,' . Auth::id(),
'description' => 'min:1|max:255'
]);
The rule expects the parameters to be the following:
the 1st parameter to be the table name, which in this case is galleries
the 2nd parameter to be the field name that is supposed to be unique and for which the value comes from the user input, which in this case is title
the 3rd parameter to be the second field name that will be added to the query conditions, which in this case is user_id
the 4th parameter to be the value of the field name passed as the third parameter
Also you can use Auth::id() since that is the short form of Auth::user()->id.
You can read more about Custom Validation rules in the Laravel Documentation.

Laravel 5.3 and above
use Illuminate\Validation\Rule;
'email' => Rule::unique('galleries')->where(function ($query) {
$query->where('user_id', Auth::id());
})
Laravel 9
use Illuminate\Validation\Rule;
Rule::unique('galleries')->where(fn ($query) => $query->where('user_id', Auth::id()))

Related

Laravel: How can I validate two optional date fields using the before and after validation rules

I'm trying to validate the date fields so that active_from needs to be a date before active_until and active_until needs to be a date after active_from.
Both fields are hidden and disabled until the user selects Yes on a select field called active.
When the user selects Yes, the active_from appears and becomes required and the active_until also appears but it's optional and here lies my problem because the validation fails whenever the active_until is not filled.
From what I've understood, if the field may or may not be enabled/exists I should use the sometimes rule which will only check the other validations if the field exists and is enabled. For e.g.
'active_from' => 'sometimes|required_if:active,yes|date|before:active_until',
The nullable rule should be used if a field may or may not be filled but should it also be used if the field may or may not exist? For e.g.
'active_until' => 'sometimes|nullable|date|after:active_from',
So my question is how can I check if active_from is before active_until only if active is selected to Yes and only if active_until is filled.
Am I using the rules correctly, should active_from only be using the sometimes rule or should it also be using the nullable rule?
Code:
$validated = $request->validate([
'title' => 'required|string|min:3|max:30|unique:categories',
'description' => 'nullable|string|min:3|max:255',
'active' => 'required|in:yes,no',
'active_from' => 'sometimes|required_if:active,yes|date|before:active_until',
'active_until' => 'sometimes|nullable|date|after:active_from',
'highlighted' => 'sometimes|required_if:active,yes|in:yes,no',
'highlighted_from' => 'sometimes|required_if:highlighted,yes|date|before:highlighted_until',
'highlighted_until' => 'sometimes|nullable|date|after:highlighted_from',
]);
I was able to finally figure it out.
This is my fixed code:
$validated = $request->validate([
'title' => 'required|string|min:3|max:30|unique:categories',
'description' => 'nullable|string|min:3|max:255',
'active' => 'required|in:yes,no',
'active_from' => 'required_if:active,yes|date',
'active_until' => 'nullable|date|after:active_from',
'highlighted' => 'required_if:active,yes|in:yes,no',
'highlighted_from' => 'required_if:highlighted,yes|date',
'highlighted_until' => 'nullable|date|after:highlighted_from',
]);
Instead of checking both dates being that one is optional even if the user selects Yes on the active select, I just need to check the active_until date (the optional one) to see if it is a valid date after the active_from date.
This way, even if the user doesn't fill the active_until date, the validation won't fail because I have the nullable rule on that field.
As for the sometimes rule, from what I've understood it only needs to be used if a field may or may not exist in the request for e.g.
'active' => 'sometimes|required|in:yes,no',
This way, it's only required if it's present in the request but since I'm using the required_if on my code, it's not necessary because it depends on the value of the other field.
For complex validaion rules
use Illuminate\Support\Facades\Validator;
....
$data = $request->all();
$validator = Validator::make($data,[
//...your unconditional rules goes here
]);
//your conditional rules goes here
$validator->sometimes('active_form', 'before:active_until', function ($request) {
return $request->filled('active_until');//if here return true,rules will apply
});
Important link
conditionally-adding-rules
retrieving-input

Laravel unique validation fails on update

I am using laravel 5.7 and using form request but i have a unique branch_name in my database as well as unique slug but every time on update valdiation erorr .branch name already exist
public function rules()
{
switch($this->method()) {
case 'DELETE':
return [
'slug'=>'required',
];
case 'POST':
case 'PUT':
case 'PATCH':
return [
'branch_name'=>'required|max:255|unique:branches,branch_name,id'.$this->id,
'branch_address'=>'required',
];
default:
break;
}
}
and also i tried the following but no use
'branch_name'=>'required|max:255|unique:branches,branch_name,'.$this->id,
and
'branch_name'=>'required|max:255|unique:branches,branch_name,slug'.$this->slug,
also i have a hidden value for both id as well as for slug even i printed in on rule method i can see id and slug
This will do:
use Illuminate\Validation\Rule;
'branch_name' => [
'required|max:255',
Rule::unique('branches')->ignore($this->route('branch')),
]
Replace "branch" with route parameter name from your edit route of web.php.
You can use this validation in add and edit both.
if your database field name is different then send the name as the second parameter in ignore function. Like
Rule::unique('branches')->ignore($this->route('branch'), 'branchName'),
Details: Laraval Validation unique
Hope this helps.
Try this one
use Illuminate\Validation\Rule;
'branch_name' => [
'required|max:255',
Rule::unique('branches')->ignore($branches->id),
],
unique:table,column,except,idColumn
The field under validation must be unique in a given database table. If the column option is not specified, the field name will be used.
validation
'branch_name' => 'required|max:255|unique:branches,branch_name,' . $this->id . ',id',
OR
'branch_name'=>'required|max:255|unique:branches,branch_name,' . $this->slug . ',slug',

Laravel validation for field if "image/file" is selected?

I have a field "image", type is file and need only to validate if image is selected, means it can be also empty.
I tried it so: 'avatar' => 'mimes:jpeg,jpg,png,gif|max:100000', but so it is also required.
I tried still with parameters present and sometimes but the field is still required.
How can I validate it only if image is selected?
If the "avatar" field may not be present in the input array you want to use:
'avatar' => 'sometimes|mimes:jpeg,jpg,png,gif|max:100000'
In some situations, you may wish to run validation checks against a field only if that field is present in the input array. To quickly accomplish this, add the sometimes rule.
If the "avatar" field will absolutely be in the input array and it's value will be then null you want to use:
'avatar' => 'nullable|mimes:jpeg,jpg,png,gif|max:100000'
The field under validation may be null. This is particularly useful when validating primitive such as strings and integers that can contain null values. To quickly accomplish this, add the nullable rule.
In your case, You have to check only if it is present or not null - Validating When there is value. So use sometimes
"In some situations, you may wish to run validation checks against a
field only if that field is present in the input array. To quickly
accomplish this, add the sometimes rule to your rule list"
$v = Validator::make($data, array(
'email' => 'sometimes|required|email',
));
In your case,
$v = Validator::make($data, array(
'avatar' => 'sometimes|mimes:jpeg,jpg,png,gif|max:100000',
));
Note:
The following code will do nothing because there are no rules to validate against, done because even if it's present in the POST array, you should specify rules. and the doesn't make any difference.
$v = Validator::make($data, array(
'avatar' => 'sometimes',
));
You could try 'nullable' in your rules.
https://laravel.com/docs/5.3/validation#rule-nullable
First check the $request object. Check avatar is available or not in your request. Then try this:
'avatar' => 'sometimes|image|mimes:jpeg,bmp,png,gif|max:2048'
the solution i found that works best is using Rule::requiredIf
'cover' => [
'image',
Rule::requiredIf(function () {
if (some_condition) {
return false;
}
return true;
})
]

Laravel 5 Validations

I want to validate my form fields using laravel 5.
Form field 1 -> User ID :
Form Field 2 -> Other Name :
Either of the form field is required.
i mean if user id is present other name should be blank and if other name is present user_id should be blank.
I am trying to use:
$validator = Validator::make(
[
'user_id ' => $user_id,
'user_name' => $user_name
], [
'user_id' => 'required_without:user_name',
'user_name' => 'required_without:user_id'
]);
if ($validator->fails()) {
return Utility::validation_err($validator);
}
While updating record even if user id is present it gives me error user id is required when other name is not present. also if i am filling out both it accepts both. It should accept one of both fields.
Any help will be appreciated.
You can use your own validation rule, for exmaple "only_one_id_name_required". It should be applied to both of fields. Next put extend Validator in App\Providers\AppServiceProvider
Validator::extendImplicit('only_one_id_name_required', function($attribute, $value, $parameters, $validator) {
return (request()->has('user_id') xor request()->has('user_name'));
});
Use extendImplicit() instead of extend() to cover empty fields request.

Laravel rule for unique excluding blank or null

I have a user model that needs to have unique email addresses but I also want to allow them to be left blank in case the user has no email...I see in docs there is a way to make a rule for unique and an exception for an id...but I'm not sure how to make this allow null or blank but unique if it is not. Sorry seems like this is simple but I can't think of the answer.
public static $adminrules =
'email' => 'email|unique:users,email,null,id,email,NOT_EMPTY'
);
Edit It may be that using the rule without required is enough since a blank or null would pass validation in those cases. I might have a related bug that making it so I can't add more than 1 blank email, so I can't verify this.
public static $adminrules =
'email' => 'email|unique:users'
);
I tried this. Adding 'nullable' before 'sometimes'.
$validator = Validator::make($request->all(), [
'email' => 'nullable|sometimes|unique:users',
]);
You should try this:
$v->sometimes('email', 'email|unique:users,email', function($input)
{
return !empty($input->email);
});
$v is your validator object and you basically say that in case the email field is not empty it should also be unique (there shouldn't be a users table record with this value in email column).
In your Requests/UserRequest you'd have something like
public function rules()
{
return [
'email' => [
'nullable',Rule::unique((new User)->getTable())->ignore($this->route()->user->id ?? null)
]
];
}
The usage of nullable is what allows the field to be nullable. The other part is to check if the email is unique in the User model table.
If you wish to validate if the field is unique
between two fields please refer to this answer.
in another table, then add the following to your rules
'exists:'.(new ModelName)->getTable().',id'
You should try to change your structure of database to make the field email is nullable. And in the rules try this :
$this->validate($request,
[
'email' => 'email',
]
);
if(isset($request->address))
{
$this->validate($request,
[
'email' => 'email|unique:users'
]
);
}

Categories