Conditional validation with Phalcon - php

There's any way to do something like this using Phalcon's validation feature:
$validation->add('telephone', new PresenceOf( [
'message' => 'The telephone is required',
'onFail' => //Validate this,
'onSuccess' => //Validate that
]));
EDIT:
Well, I asking for this because I have some validations that should run only if 2 or 3 conditions are matched in any order, so the cancelOnFail property wouldn't help me that much here.
Maybe if I create a custom validation group like $validation->add('stuff', new ComplexValidation()) but the order still a problem. The way that this validation system works is quite linear. Taking theses considerations, how can I implement more complex validations with Phalcon?

Yes. Phalcon has a validation system which works similarly. The following code would be used to ensure the 'telephone' field is supplied:
$this->validate(new PresenceOf(
array(
"field" => "telephone",
"message" => "The telephone is required"
)
));
This validator is called on the model in the validation() function. According to the documentation, the PresenceOf validator is automatically added for fields marked as ‘not null’ in the model’s table. If I understand this correctly, you actually do not need to insert this code if your field is ‘not null’, though you can do so if you want to override the default ‘validation failed’ message for this specific form. You can modify the default validation message (and supply translations) by overriding the getMessages() function in your model. There’s additional information on Phalcon's validation message system here.
The failure message is aggregated with other messages from other field validations (such as Uniqueness, for example). For each failed validation, you can access the message, field, type (and originating model). The following code would output all the information contained in the message, for each failed validation:
if ($form->save() == false) {
foreach ($form->getMessages() as $message) {
echo "Message: ", $message->getMessage();
echo "Field: ", $message->getField();
echo "Type: ", $message->getType();
echo "Model: ", $message->getModel();
}
}
I’ve noticed two different approaches to informing users of validation messages: placed together before the form (as shown here) or placed near the form input itself. If you want to output the message close to the input, you may need to iterate over each message (from getMessages()) and check for the field name which matches your input, then echo the message using getMessage().
I’m very new to Phalcon myself, so I haven’t explored all the functionality of validators, yet. There is an event system that you can use to insert code beforeValidation and afterValidation. That may be one place to look for outputting a successful validation message.

Related

How to customise the Laravel validation message property?

I am using laravel, and would like to customise the message property that is returned if there are validation errors.
{
"message": "The title field is required. (and 1 more error)",
"errors": {
"title": [
"The title field is required."
],
"slug": [
"The slug field is required."
]
}
}
Please note, I am not talking about customising the individual error messages, I am referring to customising the message property that is returned that lists the first error and how many other errors there are.
All of the error messages that Laravel uses come from the lang/en/validation.php file. Of course if no other languages used. This file is a key-value pair and based on validation rule that fails it identifies the key and gets the message. If you want to customize the message you just need to change the value of that specific key and when validation error happens the same message will be shown all over your views. If you wish you could create new rules and add custom messages for those rules as well. The way how exactly Laravel does the validation is a bit longer to describe but at the end there is an Illuminate\Support\MessageBag.php object available on your views that you use to access all the errors. That object reference is $errors. If you want to know more what you can do with this object check all the methods it offers: https://laravel.com/api/9.x/Illuminate/Support/MessageBag.html. Often for an input field there are more than one rule that should be met. Of course the following rules aren't good enough for a phone number but they do just fine for what I want to show:
$request->validate([
'numeric',
'min:10'
]);
With input like: "abc" this will fail in both cases, not a number and only three chars, at least 10. In this case MessageBag for the number as a key will have two different errors. And when you want to display you may choose which one you like. But most of the times it doesn't matter so you would choose the first one. That's why $errors->first('number');.
There are different ways of getting these errors but I'm not aware if you could modify the $errors properties. You could merge other errors but changing the value of an existing one not sure if you can do so. However if you really need to do this, consider doing something like this:
#if($errors->has('number'))
#foreach($errors->get('number') as $numberErrors)
#if($numberErrors === "**Exact error message**."))
<span>Custom error.</span>
#else
<span>{{$numberError}}</span>
#endif
#endforeach
#endif

field considered empty in FormRequest and validations

I have a template that allows adding new lines. Example: I want to add multiple products at once to a store, so I can add them all at once, through those lines that replicate themselves. The problem is that I need to validate these fields, they are all mandatory. I'm implementing so that I can walk through each one and leave it compulsory. However, I came across another problem, Laravel is telling me that my field is empty, but it is not. I would like to know how I can solve it, thank you in advance.
Here is my code to FormRequest
public function rules()
{
$rules = [];
foreach($_POST['esp'] as $key => $esp){
$name_field = "esp[" . $key . "]" . "[esprqe]"; //name of my field is complicated even as it is time based
$rules[$name_field] = 'required';
}
return $rules;
}
My template is big, no need to show.
message I receive: esp[1553533952015][esprqe]: ["The esp[1553533952015][esprqe] field is required."]
My input is not empty, I do not know what the problem is
You state the name of your field 'esprqe' is time based and complicated. This is likely the cause of your problem.
The esp['.$key.'] field is probably fine, as this field is transferred from your form. However, the value that goes into esprqe, if that is being generated in your server side code above (I don't know, you haven't provided how this field is generated), and if the rules are looking for that field to match a time-based generated field on the form... those values won't match and you will have a non-value coming into your method above.
This would very likely generate a message
["The esp[1553533952015][esprqe] field is required."]
If this is your issue, you can test by first creating a simple numbered index for the esprqe field that will be matched on both form and method. If this succeeds, you can then increase the complexity using a common generator so that the rules section knows exactly what the name of the field is. Time can't be common between form creation and rules creation - thus perhaps the reason for the failure.
You need use "dot notation" to validate attributes within an array.
$name_field = "esp.$key.esprqe";
Laravel Docs: validating arrays

Checking for empty values when saving into multiple tables with ZF2

I'm using ZF2 and mysql, but the question is platform-independent. I have a data transfer object Organization that gets hydrated from an html form. OrganizationMapper has a save method that (1) gets Organization as an argument and (2) fills a couple of database tables one after another.
Suppose the 1st table gets filled ok, but the 2nd doesn't because one of the properties of Organization isn't set (not null constraint on a column). The user gets an error, but the 1st table is already filled. If he attempts to submit the form again, but this time with all html fields filled, all the tables get filled ok, but the 1st has a previous unused row.
How could I avoid this situation?
I thought of checking for empty values with if's in the mapper's save method, but it doesn't seem elegant. I know about the InputFilter validations in ZF2, but these check the user input in the form, they don't check things when the php code communicates with the database.
Any help?
The best way is to validate all the data before you start writing it to the database.
I didn't use ZF2 and this solution is actually framework-dependent, so you need to check the ZF2 docs. For example, in Yii, you just define validation rules for every field of the model, so you can ensure that your Organization contains all the data before you start saving it to the database, probably something similar is possible in Zend.
Note, that validation doesn't mean just to check for empty values, you may need to verify different things, like: "email is correct email like xxx#yyy.com", "name is not empty", "name length is more than 3 chars", "name length is less than 1000 chars" and so on.
For Yii it roughly looks like this:
class Organization extends ActiveRecord {
...
// here we define the validation rules
public function rules() {
return [
// name is required
['name', 'required'],
// check min / max length
['name', 'string', 'min' => 3, 'max' => 12],
// check if email is valid
['email', 'email']
];
}
}
Now you can do $organization->validate() to make sure everything is correct (also when you do $organization->save() the rules will be checked before saving to the database).
And one more solution to protect from the inconsistent data is to use transactions. In the case you write to multiple tables, you anyway need them, even if you validated everything. Unexpected things happen, so it is better to protect your saving code like this (pseudo-code):
$transaction->start();
try {
$table1->writeSomeData();
$table2->writeMoreData();
$transaction->commit();
} (catch Exception $e) {
$transaction->rollback();
}
Again, check your framework documentation, it probably supports this in some way.

Laravel Custom Form Validation with Conditional Messages

I am building a Laravel-based eCommerce solution with a shopping cart. I have a page for each product where you can choose a product option, whether you want to subscribe, how often you want to receive shipments, the quantity you want, and then add it to your shopping cart. I want to validate this combination of choices before adding to the customer's shopping cart. To validate, I need to check against the database for this product option to make sure that it can be subscribed to, that the quantity chosen is below the maximum quantity allowed for that product, etc.
With CodeIgniter, I would write a custom callback, pull in the inputs from the POST request, and check everything in one call to the database. If there was a validation failure, I would then output a relevant conditional message for what caused the validation to fail. (i.e. "You can't subscribe to that product" or "The quantity you selected is more than the maximum quantity allowed for the product.")
This seems a little more difficult to accomplish with Laravel. I was looking through the documentation and articles online, and I found an approach that seems to work.
I have my validation method in my model, CartLine. Then, in a new Form Request, I overwrite the getValidatorInstance method with the following:
public function getValidatorInstance()
{
$validator = parent::getValidatorInstance();
$validator->after(function() use ($validator) {
$cartLine = new CartLine;
$cartLine->validate($this->all());
if (!$cartLine->valid()) {
$validator->errors()->add('product', $cartLine->errors());
}
});
return $validator;
}
I have a couple of questions:
When I first experimented with this solution, I tried to use method injection for the instance of CarLine inside the closure, like so:
$validator->after(function(Validator $validator, CartLine $cartLine) use ($validator) {
$cartLine->validate($this->all());
if (!$cartLine->valid()) {
$validator->errors()->add('product', $cartLine->errors());
}
});
But I kept getting an error saying that the closure was expecting an instance of CartLine and none was given. I fixed this by newing up CartLine inside the closure, but it's obviously not as elegant. Why doesn't method injection work here?
Does anyone have a better or more elegant solution for how to accomplish this type of custom validation with conditional error messages in Laravel?
you may pass the custom messages as the third argument to the Validator::make method:
$messages = [
'required' => 'The :attribute field is required.',];
$validator = Validator::make($input, $rules, $messages);
Where :attribute will be replaced by actual name of field.
Also you can provide validations only for particular attribute as below
$messages = [
'email.required' => 'We need to know your e-mail address!',];

What is the simplest way to display validation errors for hasMany associations in CakePHP 2.x?

What is the simplest way to display validation errors for hasMany associations using Model::saveAssociated() in CakePHP 2.x?
Here is an example from the CakePHP cook book.
(http://book.cakephp.org/2.0/en/models/saving-your-data.html#saving-related-model-data-hasone-hasmany-belongsto)
echo $this->Form->create('Company', array('action' => 'add'));
echo $this->Form->input('Company.name', array('label' => 'Company name'));
echo $this->Form->input('Company.description');
echo $this->Form->input('Company.location');
echo $this->Form->input('Account.0.name', array('label' => 'Account name'));
echo $this->Form->input('Account.0.username');
echo $this->Form->input('Account.0.email');
echo $this->Form->end('Add');
When validation, for example, for Account.0.email fails the form field doesn't appear to be automatically invalidated. Although the error is listed in $this->Company->Account->validationErrors.
Is there a way to automatically invalidate the appropriate field and display the corresponding validation error?
It is not 100% automated but there are things you can put together that CakePHP provides.
First of all, I am assuming you are using the latest 2.4
The solution I provide has 2 parts:
a) you validate the data at the controller level
b) you determine the error message at the FormHelper in the View level.
For part a)
you can reference this link http://book.cakephp.org/2.0/en/models/data-validation/validating-data-from-the-controller.html#validating-data-from-the-controller
Based on that link, I suggest 2 ways.
1) you can individually validate each model data.
Example,
if ($this->Company->validates(array('fieldList' => array('name', 'location')))) {
// valid
} else {
// invalid
}
and then you do a
if ($this->Account->validates(array('fieldList' => array('email')))) {
// valid
} else {
// invalid
}
Because you use a hasMany so there is a chance you may need to validate each different set of Account data separately.
Therefore you are likely to use a loop, so you can use and I quote,
if you are validating in a loop and want each set of errors separately
don’t use invalidFields(). Instead use validates() and access the
validationErrors model property.
2) second way is to use this
if ($this->Company->saveAll($this->request->data, array('validate' => 'only'))) {
// validates
} else {
// does not validate
}
You can find this at the bottom of the link I gave.
Now as for part b) displaying errors at the FormHelper.
You can read http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::error

Categories