laravel validation Array to string conversion error - laravel

if I check min|max before exist
laravel validation will return Array to string conversion error.
(laravel version 5.5)
return [
// 'nick_name' => 'exists:users|max:150|min:6|regex:/\A[0-9a-zA-Z_]{6,150}\z/',
'nick_name' => ['max:150', 'min:6', 'exists:users', 'regex:/\A[0-9a-zA-Z_]{6,150}\z/'],//return Array to string conversion error
// 'nick_name' => ['exists:users', 'max:150', 'min:6', 'regex:/\A[0-9a-zA-Z_]{6,150}\z/'],//success
'ref_code' => 'exists:users',
]

Do you change your application language? If you have translation and translation is missing you can get this error. Just change app language to en and try again.

Make sure nick_name is string. Not an array
Make sure input field name is like shown below
<input type='text' name='nick_name' /> //if name='nick_name[]' then it will be an array
//and below procedure will be used to validate it.
If it is array then validate it like shown below
nick_name.* => 'validation rule here'

Related

Laravel 9 Validation: Why am I getting 'Array to string conversion' error when I pass value in lower case?

I have an API input as follows:
a. company_name
b. county
c. state
I have entered below values for the same:
a. company_name:Some Name
c. country:in
d. state:MH
Below is my validation rule:
$rule = [
'company_name' => ['required'],
'country' => ['required', 'string', 'regex:/^[A-Z]{2}+$/','exists:table_name,column_name'],
'state' => ['required','regex:/^[A-Z]{2}+$/'],
];
The Issue:
But on testing I encountered a strange issue where if I pass the 'country' value in upper case which is intended, it works fine because in table it is in uppercase only. But if I pass it in lowercase, in which I am expecting to get validation error with help of regex, there it gives me:
ErrorException: Array to string conversion
Debugging:
This happens as soon as the lowercase value is passed to the 'exists:table_name,column_name', else there's no problem if I comment it out.
I checked lowercase string is getting passed to the table attribute.
String keyword is mentioned in the laravel validation part against the field.
Question:
It should have thrown validation of lowercase regex before moving ahead with the table lookup, right?
What to do if I want to validate in that way? So what could be issue?
My expected output:
Getting validation error of the mentioned field to be in uppercase like this:
{
"status": false,
"status_code": 400,
"message": "Request validation error.",
"validation": {
"country": [
[
"Country should be in captial alphabetic letters of 2 characters in length."
]
]
}
}
Thanks in advance.
Assuming you want to check countries on 2 letter for example like UK I suggest installing a libary like League\ISO3166 then make a custom validation rule that looks something like this
public function passes($attribute, $value): bool
{
if (! is_string($value)) {
return false;
}
$iso3166 = new ISO3166();
try {
$iso3166->alpha2($value);
return true;
} catch (DomainException|OutOfBoundsException $exception) {
return false;
}
return false;
}
This libary also check for u if the country tag is this case is a valid ISO3166 meaning for example NL passes but EP is non existing country so it will fail
I know this is not a regex solution but this prob will even work better in this use case
Laravel has built in uppercase rule. It will return an error in cases where any character is lowercase.

Laravel Phpunit, AssertJsonFragment not working as expected

I've done this thousands of times on past projects, but I feel since moving to laravel 8 on our latest application something has changed.
I used to be able to do something as simple as:
$response = $this->post('/api/team', []);
$response->assertJsonFragment([
"The team name field is required."
]);
However when running the test I get the following error:
1) Tests\Feature\Controllers\Team\CreateTest::teamNameRequired
Unable to find JSON fragment:
[["The team name field is required."]]
within
[["{\"team_name\":[\"The team name field is required.\"]}"]].
Failed asserting that false is true.
I've tried swapping to assertJson and a couple others but ideally this is how I'd like to assert, I also could create a separate function or use some other helpers but I want to assert not just that there has been a validation error, but a specific one.
I'm using the standard laravel validator and response object for context:
$validator = Validator::make($request->all(), [
'name' => 'required|string|between:2,100'
]);
if($validator->fails()){
return response()->json($validator->errors()->toJson(), 400);
}
This was caused because I was json encoding the errors twice.
Within my controller the following if statement should have been used:
if($validator->fails()){
return response()->json($validator->errors(), 400);
}

Laravel validate request filter field with dot (period) in field name

Here is to validate form request in laravel, request contains filter and field name in the filter has period(dot) present.
Sample Request url
...?filter[entity.abc][]='value'
Here entity.abc is actually a string, but laravel considers it to be array of object, when rule is given for 'filter.entity.abc'
filter:[
[entity]: [ {abc:'value'}]
]
which is actually
filter:[
[entity.abc]:['value']
]
So we need to make regex for second dot, which equivalents to:
public function rules()
{
return [
'filter.entity\.abc' => ['bail', 'sometimes', 'array'],
'filter.entity\.abc' => ['uuid']
];
}
Above always retuns true,even when invalid uuid is present
why not modify your request like this?
...?filter[entity][abc][]='value'
Edit:
You can use custom validation in laravel where you can deconstruct the parameters and check the values manually
Laravel Custom Validation
https://laravel.com/docs/8.x/validation

Laravel send query string with optional parameters

I have my route set as
Route::any('/{brand?}/{type?}/{city?}', 'SearchController#index')->name('search');
I want to send from my controller query strings (Form GET params)
After searching I ended up with this but it does not work properly
return redirect()->route('search', [$brand->name, $type->name, 'search_model_from' => $request->search_model_from, 'search_model_to' => $request->search_model_to]);
which returns back
localhost:8000/toyota/avalon/2018?search_model_to=2019
I want to return
localhost:8000/toyota/avalon/?search_model_from=2018&search_model_to=2019
What I am trying to achieve in general is SEO friendly search functionality
Maybe you should try to assign city as null like that :
return redirect()->route('search', [
'brand' => $brand->name, 'type' => $type->name,
'city' => '', 'search_model_from' => $request->search_model_from,
'search_model_to' => $request->search_model_to
]);
I'm not sure but this could happen because you have defined 3 optional parameters in the route and as you are sending just two of them, this might takes the next (in this case 'search_model_from') as the third parameter for url.
Maybe if you cast and set a default value to the optional parameters in your Controller, you won't have that trouble, like this:
public function index(string $brand='', string $type='', string $city='' , $other_parameters)

Laravel before/after validation message

In Laravel you can make a custom messages for validators. But I found that the prepared messages are little bit wrong. With before and after validation rules, the parameter is converted with strtotime like that said in the documentation.
So if I set rule 'expires' => 'before:+1 year' the rule is working and correct. But if the user inputs a wrong value, Laravel prints the message like that:
The expires must be a date before +1 year
This message is very unclear for the average client. I was expected that the message will be converted with the strtotime also.
There is a clean way to print more clear error message?
You can override the validation messages with a custom ones if you want to.
In the Form Request class, add the following method and change the messages like so:
public function messages()
{
return [
// 'fieldname.rulename' => 'Custom message goes here.'
'email.required' => 'Er, you forgot your email address!',
'email.unique' => 'Email already taken m8',
];
}
Update:
If you want to change the global messages, you can open the validation.php file inside resources/lang/en/validation.php and edit the message there.
You can user AppServiceProvider.php
and you can write your new validation rule there and set your error message in validation.php file
/app/Providers/AppServiceProvider.php
/resources/lang/en/validation.php
Ex:
Validator::extend('before_equal', function ($attribute, $value, $parameters) {
return strtotime(Input::get($parameters[0])) >= strtotime($value);
});
and the message is
'before_equal' => 'The :attribute field is only accept date format before or equal to end date',
Please try this and you can alter this to based on your require.

Resources