Laravel nullable validation rule not working - php

I recently upgraded to laravel 5.4 (from 5.2) to make use of the nullable validation rule.
I have a field act_post_code which can be either an integer OR null. So I provided the following rule in my Request class.
'act_post_code' => 'integer|nullable'
In Postman using form-data, I provide a key = act_post_code with its value = null.
The response I get is the following:
{
"act_post_code": [
"The act post code must be an integer."
]
}

Explanation:
Unfortunately, it seems that nullable is only valid with certain other validations.
For example: 'act_post_code' => 'nullable|integer' will give you the error: "validation.integer"
However, 'act_post_code' => 'nullable|date' works fine.
Fix:
As a work around for these validations, you can make them dynamic. For example, before the validator:
$act_post_code_rules = $request->act_post_code ? 'integer' : '';
then, within the validate:
'act_post_code' => $act_post_code_rules

In order to validate the field act_post_code which can be either be of type integer or nullable, you can try out the following :
When declaring in the migration ,the Schema of the table where there is the column act_post_code declare the column like $table->integer('act_post_code')->nullable();
This one might just work for you to validate 'act_post_code' =>'sometimes|nullable|integer'

One can die and dump request parameters and check whether the actual value is null or "null" (in string). Sometimes when submitting a form via javascript we use FormData() to append data to the form, in those scenarios it may send a null value as in string type "null"
array:5 [
"firstName" => "Kaustubh"
"middleName" => "null" // null as string
"lastName" => "Bagwe"
"contactNumber" => null // null value
"photo" => null
"_method" => "PUT"
]

Open your migration file and make the this field as nullable
For e.g
Schema::create('your_table_name', function (Blueprint $table) {
$table->integer('act_post_code ')->nullable();
});
Make sure it is present in your model file in the fillable section
protected $fillable = ['act_post_code'];

After Some Test I found that nullable rule only work if only the data that we pass really was a null data.
so in my test case i use the validation rule like this :
"counter" => "nullable|numeric"
and in the blade file, I use Form::text('counter','') as element to input my data.
Then i use it with few test case:
When I input the counter data with a non-numeric value it will response with error: "the counter must be a number".
When I input the counter data with a numeric value it will pass the validation test.
When I not input any data to the counter it will pass the validation test.
so i check the data manually using dd($request_data)or if you using ajax just return $request_data and print it using console.log("data") like:
$.ajax({
type:'POST',
data:{_token:"{{ csrf_token() }}",
counter:$('input[name="counter"]').val()
},success:function(data){
console.log(data);
}
});
and found out that when input field is emptied it will give the null value.

Related

Differences between sometimes and nullable in Laravel validation

Let's assume I can do validation in two ways
'active' => {
'sometimes',
}
and
'active' => {
'nullable',
}
What's the difference? When the one will pass and the other won't?
And the same question about this:
'user_id' => {
'sometimes|exists:user,id',
}
and
'user_id' => {
'nullable|exists:user,id',
}
I've read multiple posts on a subject, including the documentation and I still don't get it. Does sometimes or nullable make even sense when using with no other rules (like in my first example)?
Nullable:
Laravel converts empty value to null using middleware ConvertEmptyStringsToNull. Because of this, you will often need to mark your "optional" request fields as nullable if you do not want the validator to consider null values as invalid.
Sometimes :
If you want to validate the field only if the field is present in request. This is useful when we manipulate the DOM using javascript or jQuery.
Read More

Laravel Validation Integer accepts empty string?

Im creating some small API with which i can create blog posts through postman. Im using laravel 5 and i encoutered a problem.
In the API call, i can specify a user id, so the post is written by someone else than whoever makes the API call right now. My currently logged in user is specified with a token in postman.
So my problem is now, when i create the API call and specify my user_id as empty string
"userID": ""
it will throw an error, because i specified the id to be an int like so
'userID' => ['integer']
The error is
"Type error: Argument passed to construct() must be of the type integer or null, string given",
Why does it accept an empty string? How can i validate that correctly?
Note that the userID doesn't have to be specified in the post request. If not specified, it will just take the one from the user you are currently logged in with. (Specified in the token)
Using two validation rules together will fix the issue.
required and integer
and as you said, you dont want to make it mandatory:
use these validation rules combination:
nullable|integer
I had this problem. So, I found this description in the laravel docs:
"By default, when an attribute being validated is not present or contains an empty string, normal validation rules, including custom extensions, are not run."
So... when you have an attribute with empty string data, the normal validation rules are not executed.
So... I had an idea to solve this problem which was override the function setAttribute in my models:
public function setAttribute($key, $value)
{
parent::setAttribute($key, $value);
if (is_string($value))
{
$this->attributes[$key] = empty(trim($value)) ? null : $value;
}
}
So... All times that will have to save de model in your database, the empty values will be converted in a null values.
Therefore, if the data is null or integer, use the "nullable | integer" rule to use the validation rule. If the data is an empty string, the validation rule will not be considered, but the data will be converted to an empty string before being saved to the database.
I created a my BaseModel(abstract class) with the method setAttribute and all my models inherit this class.
abstract class BaseModel extends Model
{
public function setAttribute($key, $value)
{
parent::setAttribute($key, $value);
if (is_string($value))
{
$this->attributes[$key] = empty(trim($value)) ? null : $value;
}
} ...
You need to make userId field required as this:
'userId' => 'required|integer'

Form checkbox field value is not getting passed to Laravel controller

In my registration form, I have a checkbox where a user can accept to receive newsletters.
In create function I want to display all passed data:
protected function create(array $data)
{
dd($data);
}
The name of my checkbox field is newsletter. When I do dd(), I don't get the value for the newsletter, only for: name, email and password.
If I add this newsletter to Validator then it is shown.
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
'newsletter' => 'required',
]);
}
Now, when I do dd() it is passed, but I don't want this checkbox to be required. It should be optional. Should I change something in Validator or?
Regardless of the backend, when a checkbox is not checked, its value won't be sent as part of the request to the server. That's how browsers work and that's why you won't be seeing a newsletter field when dumping the request.
However, when you use Laravel's validator and mention the field in the rules, Laravel does it for you and sets its value. To not to make it required, use the sometimes rule.
That would do it just for the purpose of dumping the data. But when implementing the real logic, instead of dumping data, you'll hopefully be utilizing the given request instance, facade or helper which will return a falsy value for non-existent parameters. So, you're just fine without adding the additional rule.
Or, you can set a default value for the newsletter field making sure if the data is not there, new registrations will happen with the desired default state.
By the way, you wanna make sure that your controller method is accepting a Request instance instead of an array.
Your newsletter field is a checkbox. When a html form is submitted and the checkbox is not checked, this field will not be available in the posted data. If the checkbox is checked it will be available. This is default html behavior, nothing you can do about this.
To check if the checkbox has been checked in your code, you can use the following:
$checked = array_key_exists('newsletter', $data);

Laravel Carbon data missing when date is an empty string

In my model I have the following:
protected $dates = ['start_date'];
I am using an input field of type 'date' to select the date. If the user removes the date, its value becomes a null string "".
when updating my model, I get the following error:
exception: "InvalidArgumentException"
file: "C:\www\projects\crm\vendor\nesbot\carbon\src\Carbon\Carbon.php"
line: 582
message: "Data missing"
I can avoid this error by using a mutator like this:
public function setStartDateAttribute($value)
{
if ($value) {
$this->attributes['start_date'] = $value;
} else {
$this->attributes['start_date'] = null;
}
}
Question:
Is there a faster/better way than using a mutator to deal with storing an empty string as a date?
Looking into this a bit deeper:
Middleware updated in 5.4
Laravel 5.4 included two new middleware in the default middleware stack: TrimStrings and ConvertEmptyStringsToNull.
These middleware will automatically trim request input values and
convert any empty strings to null. This helps you normalize the
input for every request entering into your application and not have to
worry about continually calling the trim function in every route and
controller.
From: https://laravel.com/docs/5.4/releases#laravel-5.4
So, when I am grabbing the request object, an empty date field is converted to null. The database allows null on these fields and everything works correctly.
So, through the front end, date fields can be entered and removed without error. When updating manually to an empty string as per your request
\App\Yourmodel::find(7)->update(["your_date_field" => ""]);
I had the same data missing error.
Question is, do you specifically need to pass an empty string or is making the field nullable a better option for you?
\App\Yourmodel::find(7)->update(["your_date_field" => null]);

FormRequest method to ignore null field upon validation in L5.4

I've a Form Request with this rule:
"password" => "confirmed"
This solution works well in L5.3 because the rule itself has a bug, if you pass two empty fields like
"password" => "",
"password_confirmation" => ""
they will be validated because both are empty strings ("").
Even though this is a bug, I guess, it's fine in a certain degree because my application does other checks after the request anyway but in L5.4 every empty fields are converted to null and the "confirmed" rule alone does not work anymore because of the new middleware.
I tried:
"password" => "sometimes|confirmed"
but it does not work because the key exists.
My question is simple:
Is there a validation rule that works similar to sometimes but it checks nullable values instead?
I would like to keep the middleware though.
Use the nullable validation rule.
https://laravel.com/docs/5.4/validation#rule-nullable

Categories