Nested alternative validation required_without in laravel 5.8 - laravel

here is my request
{
"formulations": [
{
"formulation_id": null,
"formulation_custom_name": "test",
"meal_time_id": null,
"remark": "demo1"
},
{
"formulation_id": 3,
"formulation_custom_name": "asd",
"meal_time_id": 2,
"remark": "demo"
}
]
}
validation rule
'formulations.*.formulation_id' => 'required_with:formulations.*.formulation_custom_name'
working properly for first object i.e formulation_id is required when formulation_custom_name is present
"errors": {
"formulations.0.formulation_id": [
"The formulations.0.formulation_id field is required when formulations.0.formulation custom name is present."
]
}
now my question is exactly opposite from above scenario i.e validate
formulation_custom_name required when formulation_id is null or not present
like
'formulations.*.formulation_id' => 'required_without:formulations.*.formulation_custom_name'
but this is not working for this request like this
{
"formulations": [
{
"formulation_id": 6,
"formulation_custom_name": "test",
"meal_time_id": null,
"remark": "demo1"
}
}
thanks in advance

required_without rule in Validator checks for field existence/presence and not for empty value or null value.
So you need required_if here, and use like below
'formulations.*.formulation_id' => 'required_if:formulations.*.formulation_custom_name,' // it will work for blank and null
Or if you need more complex condition then you can use requiredIf custom Rule
or if you need vice versa then write like below
'formulations.*.formulation_custom_name' => 'required_without:formulations.*.formulation_id'
Document Link

Related

Fluent Validation and ASP.NET Core 6 Web API

I am new to fluent validation and also a beginner in Web API. I have been working on a dummy project to learn and your advice will be much appreciated. After following the FluentValidation website, I was able to successfully implement fluent validation.
However, my response body looks very different and contains a lot of information. Is it possible to have a regular response body with validation errors?
I will put down the steps I took to implement fluent validation. your advice and help are much appreciated. I am using manual validation because based on the fluent validation website they are not supporting the auto validation anymore.
In the program file, I added
builder.Services.AddValidatorsFromAssemblyContaining<CityValidator>();
Then I added a class that validated my City class which has two properties Name and Description:
public class CityValidator : AbstractValidator<City>
{
public CityValidator()
{
RuleFor(x => x.Name)
.NotNull()
.NotEmpty()
.WithMessage("Please specify a name");
RuleFor(x => x.Description)
.NotNull()
.NotEmpty()
.WithMessage("Please specify a Description");
}
}
In my CitiesController constructor I injected Validator<City> validator; and in my action, I am using this code:
ValidationResult result = await _validator.ValidateAsync(city);
if (!result.IsValid)
{
result.AddToModelState(this.ModelState);
return BadRequest(result);
}
The AddToModelState is an extension method
public static void AddToModelState(this ValidationResult result, ModelStateDictionary modelState)
{
if (!result.IsValid)
{
foreach (var error in result.Errors)
{
modelState.AddModelError(error.PropertyName, error.ErrorMessage);
}
}
}
On post, I am getting the response as
{
"isValid": false,
"errors": [
{
"propertyName": "Name",
"errorMessage": "Please specify a name",
"attemptedValue": "",
"customState": null,
"severity": 0,
"errorCode": "NotEmptyValidator",
"formattedMessagePlaceholderValues": {
"PropertyName": "Name",
"PropertyValue": ""
}
},
{
"propertyName": "Description",
"errorMessage": "Please specify a name",
"attemptedValue": "",
"customState": null,
"severity": 0,
"errorCode": "NotEmptyValidator",
"formattedMessagePlaceholderValues": {
"PropertyName": "Description",
"PropertyValue": ""
}
}
],
"ruleSetsExecuted": [
"default"
]
}
While the regular response without Fluent Validation looks like this:
{
"errors": {
"": [
"A non-empty request body is required."
],
"pointofInterest": [
"The pointofInterest field is required."
]
},
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-1a68c87bda2ffb8de50b7d2888b32d02-94d30c7679aec10b-00"
}
The question: is there a way from the use the fluent validation and get the response format like
{
"errors": {
"": [
"A non-empty request body is required."
],
"pointofInterest": [
"The pointofInterest field is required."
]
},
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-1a68c87bda2ffb8de50b7d2888b32d02-94d30c7679aec10b-00"
}
Thank you for your time.
Updated ans:
with your code, you can simply replace.
return BadRequest(result); // replace this line with below line.
return ValidationProblem(ModelState);
then you get same format as required.
------------------------*----------------------------------------
Please ignore this for manual validation.
You don't need explicit validation call.
this code is not required:
ValidationResult result = await _validator.ValidateAsync(city);
if (!result.IsValid)
{
result.AddToModelState(this.ModelState);
return BadRequest(result);
}
it will auto validate the model using your custom validator.
you simply need this
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
and it will give you errors in the require format.
if(!result.IsValid)
{
result.AddToModelState(this.ModelState);
return ValidationProblem(ModelState);
}

Laravel validation Form - Don't accept number into double quotes

I have this POST request:
{
"documentType": "1",
"metadata": []
}
And i have this validation rules:
const POST_RULES = [
'documentType' => 'required|int',
'metadata' => 'array',
];
The problem is:
I don't want accept this value of documentType ("1") because it's a string. Users of the application can send a string.
I need to accept only number (1, 2, 3, 4 etc ...) whitout double quotes.
It's possible to create rule for that ?
Thank's in advance,
In the POST request, send number without quotes
{
"documentType": 1,
"metadata": []
}
You required an INT, not a STRING.
Or, you can accept the "1" and then check if that is a number:
if (is_numeric($request->documentType)) {
// Do other stuff
return true
}

API Platform - Adding new entity with subresource

As far as I can see this isn't possible but I thought I'd ask in case I've missed something.
I have 2 entities, Rule and Condition
One Rule can have many Conditions
What I'm trying to achieve is adding a new Rule with one or more Conditions in a single request
I've tried the following via POST
{
"property": "id",
"conditions": [
{
"position": 1
}
],
"title": "getId",
"position": 1
}
Conditions have a rule_id column, but I obviously can't set it at this point as it hasn't been created yet
That request gives me the error
Nested documents for attribute "conditions" are not allowed. Use IRIs instead.
Of course, I can't use an IRI because I haven't created the condition yet, and I can't create the condition first as it would fail foreign key checks
So am I right in thinking this isn't possible or am I just doing it wrong?
Thanks in advance
You need to add the same serialization group to both the Rule and Condition classes, as explained here.
Also you must add the cascade={"persist"} attribute to the #OneToMany annotation of the Rule::conditions property.
Something like that:
// src/EntityRule.php
#[ORM\Entity(repositoryClass: RuleRepository::class)]
#[ApiResource(
collectionOperations: [
"post" => [
"denormalization_context" => [ "groups" => ["write:rule"]]
]
]
)]
class Rule
{
// ...
#[ORM\OneToMany(mappedBy: "rule", targetEntity: Condition::class, cascade: ["persist"])]
#[Groups(["write:rule"])]
/**
* #var Condition[]
*/
private Collection $conditions;
// ...
}
// src/Entity/Condition.php
#[ORM\Entity(repositoryClass: ConditionRepository::class)]
#[ApiResource(
collectionOperations: [
"post" => [
"denormalization_context" => ["groups" => ["write:condition"]
]
]
]
)]
class Condition
{
// ...
#[ORM\Column(nullable=false, unique=false)]
#[Groups(["write:condition", "write:rule"])]
private int $position;
// ...
}

Laravel 5.1 Date_Format Validator Fails on Y-m-d Format

I'm starting to use Request objects to validate incoming post data, and I've seen examples of how others are using date_format, but I can't seem to get dates to pass even though I'm using a format that passes when you use PHP's date_parse_from_format:
print_r(date_parse_from_format('Y-m-d','2015-07-27'));
Output
UPDATE: their is a warning in date_parse_from_format, but I don't understand why as it reflects the format.
{
"year": 2015,
"month": 2,
"day": 30,
"hour": false,
"minute": false,
"second": false,
"fraction": false,
"warning_count": 1,
"warnings": {
"10": "The parsed date was invalid"
},
"error_count": 0,
"errors": [],
"is_localtime": false
}
Validator
public function rules()
{
return [
'rental_id' => 'required|exists:rentals,id',
'start_at' => 'required|date_format:Y-m-d',
'end_at' => 'required|date_format:Y-m-d'
];
}
Using PostMan I'm sending in a payload of:
rental_id = 1 as text
start_at = 2015-02-30 as text
end_at = 2015-02-30 as text
And it throws a NotFoundHttpException, but if I comment out start_at and end_at in the validator request it passes, and enters my controllers action with the proper payload:
{
"rental_id": "1",
"start_at": "2015-02-30",
"end_at": "2015-02-30"
}
Apparently, the date_format validation failed as I randomly chose 2015-02-30 to test my API, but that day doesn't exist as that would be February 30... oh the shame and the wasted time. Thanks to #ceejayoz for all the help!!!

What is the best way to validate data in mongo?

What's the best way to validate data being inserted or updated into MongoDB? Is it to write some sort of server executed Javascript code that does the validation?
Starting from MongoDB 3.2 they added document validation (slides).
You can specify validation rules for each collection, using validator option using almost all mongo query operators (except $geoNear, $near, $nearSphere, $text, and $where).
To create a new collection with a validator, use:
db.createCollection("your_coll", {
validator: { `your validation query` }
})
To add a validator to the existing collection, you can add the validator:
db.createCollection("your_coll", {
validator: { `your validation query` }
})
Validation work only on insert/update, so when you create a validator on your old collection, the previous data will not be validated (you can write application level validation for a previous data). You can also specify validationLevel and validationAction to tell what will happen if the document will not pass the validation.
If you try to insert/update the document with something that fails the validation, (and have not specified any strange validationLevel/action) then you will get an error on writeResult (sadly enough the error does not tell you what failed and you get only default validation failed):
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
MongoDB doesn't have constraints or triggers so the application has to validate the data.
You can also write Javascript scripts that check once a day or more if there is invalid data. You can use this to check the quality of the business logic of your application.
I think it would be normal for your app to handle this kind of thing. If the data is invalid in some way, don't let it get added to the datastore until the user has corrected whatever error you have detected.
Starting in 2.4, MongoDB enables basic BSON object validation for mongod and mongorestore when writing to MongoDB data files. This prevents any client from inserting invalid or malformed BSON into a MongoDB database.
source: http://docs.mongodb.org/manual/release-notes/2.4/
Starting MongoDB 3.6 you can also use JSON Schema to express validation rules. These checks will happen on the database side on insert/update.
Here is an example from the docs:
validator = {
$jsonSchema: {
bsonType: "object",
required: [ "name", "year", "major", "address" ],
properties: {
name: {
bsonType: "string",
description: "must be a string and is required"
},
year: {
bsonType: "int",
minimum: 2017,
maximum: 3017,
description: "must be an integer in [ 2017, 3017 ] and is required"
},
major: {
enum: [ "Math", "English", "Computer Science", "History", null ],
description: "can only be one of the enum values and is required"
},
gpa: {
bsonType: [ "double" ],
description: "must be a double if the field exists"
},
address: {
bsonType: "object",
required: [ "city" ],
properties: {
street: {
bsonType: "string",
description: "must be a string if the field exists"
},
city: {
bsonType: "string",
description: "must be a string and is required"
}
}
}
}
}
}
db.runCommand( {
collMod: "collectionName",
validator: validator
} )
I've just started using MongoDB and PHP together, inside a Zend Framework based application.
I have created 1 object for each MongoDB collection (e.g. User.php maps to the user collection). Each object knows what collection it maps to, and what fields are required. It also knows which filters (Zend_Filter_Input) and validators (Zend_Validate) should be applied to each field. Before doing a MongoDB insert() or save(), I run $object->isValid(), which executes all the validators. If they all pass isValid() will return true, and I proceed to run the insert() or save(), otherwise I display the errors.

Resources