hi guys i'm new in laravel and for my question i searched many post but cannot find any solution for that i'm be thankful if you have any guide or solution.
i made a unique rule with where but its not work and return null value so how i do this in right way?
in my case i need to check column 'last_ingameChange' value must lower than time() else validation need to return error message "you just have 1 week to make change your in-game username"
public function validator(array $data, array $rules)
{
return Validator::make($data, $rules);
}
public function updateUserAccount(Request $request, $id)
{
$rules = [
'required|min:5|max:255|unique:users,ingame_name,'.$id.'|'.Rule::unique('users')->where('last_ingameChange', '<', time())
];
$rr = $this->validator([$request->input('ingame_name')], $rules);
dd($rr);
}
but the initialRules is:
"ingame_name" => "required|min:5|max:255|unique:users,ingame_name,1|unique:users,NULL,NULL,id"
What you are doing will simply not work because:
You need to provide a validation field
The Rule::unique will return a Rule instance and not a string so you can't concatenate that to another string or you may force it to coerce to a string which will obviously lose any information you had in the where.
You can use an array to contain the rules:
$rules = [
'ingame_name' => [ //Field name
"required",
"min:5",
"max:255",
"unique:users,ingame_name,$id",
Rule::unique('users', 'ingame_name')
->using(function ($q) { $q->where('last_ingameChange', '<', time()); })
]
];
$this->validator($request->all(), $rules);
As #MikeFoxtech suggested it is preferable to use a before rule however
Try this
Rule::unique('users')->ignore($id, 'ingame_name')->where(function ($query) {
return $query->where('last_ingameChange', '<', time());
})
Related
I am using the Lumen Framework, which utilizes the Laravel Validation
I wanted to create a Validator Rule to make the Request->input() json only contain specific keys at the root like "domain" and "nameservers". Not more and not less.
Example passing the rule:
{
"domain":"domain.tld",
"nameservers":
{...}
}
Example not passing the rule:
{
"domain":"domain.tld",
"nameservers":
{...},
"Hack":"executeSomething()"
}
I tried to use to use several default validation rules to achieve this but wasnt successful.
My approach was now to put the request in another array like this
$checkInput['input'] = $request->all();
to make the validator validate the "root" keys.
Now this is my Approach:
create the validator
$checkInput['input'] = $request->all();
$validator = Validator::make($checkInput, [
'input' => [
'onlyContains:domain,nameservers'
],
]);
creating the rule
Validator::extend('onlyContains', function($attribute, $value, $parameters, $validator){
$input = $validator->getData();
$ok = 0;
foreach ($parameters as $key => $value) {
if (Arr::has($input, $attribute . '.' . $value)) {
$ok++;
}
}
if (sizeof(Arr::get($input, $attribute)) - $ok > 0) {
return false;
}
return true;
});
It seems i got the desired result, but i am asking if there is maybe smarter solution to this with the default rules provided by Laravel/Lumen.
You are trying to do a blacklisting approach blocking out fields that are not intended. A simple approach, that is utilized a lot, is to only fetch out the validated. Also you are trying to do logic, that goes against normal validation logic, to do it a field at a time.
This is also a good time, to learn about FormRequest and how you can get that logic, into a place where it makes more sense.
public function route(MyRequest $request) {
$input = $request->validated();
}
With this approach, you will only ever have the validated fields in the $input variable. As an extra bonus, this approach will make your code way easier to pick up by other Laravel developers. Example form request below.
public class MyRequest extends FormRequest
{
public function rules()
{
return [
'domain' => ['required', 'string'],
'nameservers' => ['required', 'array'],
];
}
}
You should use prohibited rule.
For eg:
$allowedKeys = ['domain', 'nameservers'];
$inputData = $request->all();
$inputKeys = array_keys($inputData);
$diffKeys = array_diff($inputKeys, $allowedKeys);
$rules = [];
foreach($diffKeys as $value) {
$rules[$value] = ['prohibited'];
}
I want to check my request datetime with many format look like below format:
Y-m-d
Y-m-
Y-m
In Laravel, I use Validator to validate datetime, but Validator can not make checking with many format. This is my code:
Validator::make(['date' => $departureDate], [
'date' => 'required|date_format:Y-m-d, Y-m, Y-m-'
]);
How can I do it in laravel
Please help me! Many thanks!
You must write a custom validation format for that. Laravel's date_format expects only one parameter and not capable of handling multi-formats. There are Two ways to add custom validation. first, one is making a rule repository and add your validation logic there. Here Taylor Otwell explained this method.
The other way to doing that is extend validation in app service provider and add new rule there. add this code in app service provider:
use Illuminate\Support\Facades\Validator;
Validator::extend('multi_date_format', function ($attribute, $value, $parameters,$validator) {
$ok = true;
$result = [];
// iterate through all formats
foreach ($parameters as $parameter){
//validate with laravels standard date format validation
$result[] = $validator->validateDateFormat($attribute,$value,[$parameter]);
}
//if none of result array is true. it sets ok to false
if(!in_array(true,$result)){
$ok = false;
$validator->setCustomMessages(['multi_date_format' => 'The format must be one of Y-m-d ,Y-m or Y-m-']);
}
return $ok;
});
And here you can use it this way:
$validator = Validator::make(['date' => '2000-02-01'], [
'date' => 'required|multi_date_format:Y-m-d,Y-m,Y-m-'
]);
if($validator->fails()) {
$errors = $validator->errors()->all();
}
You can register custom validator in file app/Providers/AppServiceProvider.php in boot method.
Validator::extend('several_date_format', function ($attribute, $value, $parameters,$validator) {
foreach ($parameters as $parameter){
if (!$validator->validateDateFormat($attribute,$value,[$parameter]))
return false;
}
return true;
});
Now you can use it
'your_date' => 'required|several_date_format:Y-m-d,...'
Optional after it you can add custom message in resources/lang/en/validation.php
return [
...
'several_date_format' => 'Error text'
...
]
Currently in lumen when you use the $this->validate($request, $rules) function inside of a controller it will throw a ValidationException with error for your validation rules(if any fail of course).
However, I need to have a code for every validation rule. We can set custom messages for rules, but I need to add a unique code.
I know there's a "formatErrorsUsing" function, where you can pass a formatter. But the data returned by the passed argument to it, has already dropped the names of the rules that failed, and replaced them with their messages. I of course don't want to string check the message to determine the code that should go there.
I considered setting the message of all rules to be "CODE|This is the message" and parsing out the code, but this feels like a very hacked solution. There has to be a cleaner way right?
I've solved this for now with the following solution:
private function ruleToCode($rule) {
$map = [
'Required' => 1001,
];
if(isset($map[$rule])) {
return $map[$rule];
}
return $rule;
}
public function formatValidationErrors(Validator $validator) {
$errors = [];
foreach($validator->failed() as $field => $failed) {
foreach($failed as $rule => $params) {
$errors[] = [
'code' => $this->ruleToCode($rule),
'field' => $field,
];
}
}
return $errors;
}
I have been using the following validation for my form in Laravel:
public function isValid($data, $rules)
{
$validation = Validator::make($data, $rules);
if($validation->passes()){
return true;
}
$this->messages = $validation->messages();
return false;
}
The rules passed to it are simple:
$rules = [
'name' => 'required',
'type' => 'required'
];
And $data is the input post data. Now I need to add a custom validation extension to this, specifically to make sure that the value of input field round2 is greater than the value of input field round1. Looking at the docs, I have tried the following syntax which I think should be correct, but I keep getting an error.
$validation->extend('manual_capture', function($attribute, $value, $parameters)
{
return $value > $parameters[0];
});
Then I could call this with $attribute = 'round1', $value = $data['round1'] and $parameters = [$data['round2']].
The error is Method [extend] does not exist. - I'm not sure if my understanding of this whole concept is correct, so can someone tell me how to make it work? The docs only have about 2 paragraphs about this.
Put the following in your route.php
Validator::extend('manual_capture', function($attribute, $value, $parameters)
{
return $value > $parameters[0];
});
Additional documentation here
Then use it like so:
$rules = [ 'foo' => 'manual_capture:30'];
I have a table called taxonomy. It's columns are id, name, slug, type (tag, category). I have created a separate controller for tag and category.
Now I need to apply a unique validation rule on slug:
where type = tag
Unique rule with the additional where clause
'slug' => Rule::unique('taxonomy')->where(function ($query) {
return $query->where('type', 'tag');
})
You can apply unique rule like this for insert and update both in single validation function.
public function validateTaxonomy(Request $request){
if(isset($request->id) && $request->id){
$id = ','.$request->id.',id,type,'.$request->tag;
}else{
$id = ',Null,id,type,'.$request->tag;
}
$rules = [
'slug' => 'required|unique:taxonomy,slug'.$id,
];
return Validator::make($request->all(), $rules);
}
Example to call from store function
public function store(Request $request)
{
$validator = $this->validateTaxonomy($request);
if($validator->fails()){
return redirect()->back()->withErrors($validator)->withInput();
}
...
}
Try this:
'postData' => 'unique:table_name,column_name'
see more validation here:
Validation Laravel
Unique rule with the additional where clause
'slug' => Rule::unique('taxonomy')->where('type', 'tag')