How can I get validated json value using Apigility. For example, I need to get validated user_id under users collection in the following json data.
{
"log_type": "split food",
"meal_type": "Break Fast",
"meal_date": "12-2-2015",
"users": [
{
"user_id": 1,
"food_details": [
{
"food_id":101
}
]
}
]
}
I know fields can be validated through apigility but here is from json.
Thank you
You should look into the documentation of ZF2 validation for validating (form) collections. Some documentation on this can be found here.
You should set the type field like this:
'type' => 'Zend\InputFilter\CollectionInputFilter',
for validation of nested objects (or form field sets) you need to set the type field as follows:
'type' => 'Zend\InputFilter\InputFilter'
You use it like this:
'input_filter' => array(
'log_type' => array(
'validators' => array(
// ... validators ...
),
'filters' => array(
// ... filters ...
),
),
'meal_type' => array(
'validators' => array(
// ... validators ...
),
'filters' => array(
// ... filters ...
),
),
'meal_date' => array(
'validators' => array(
// ... validators ...
),
'filters' => array(
// ... filters ...
),
),
'users' => array(
'required' => true,
'count' => ... optional count ...
'input_filter' => ... input filter or input filter config to use for each element ...
'type' => 'Zend\InputFilter\CollectionInputFilter',
),
'some_complex_element' => array(
'property_of_complex_element' => array(
'name' => 'property_of_complex_element',
'required' => false,
'validators' => array(
// ... validators ...
),
'filters' => array(
// ... filters ...
),
),
'type' => 'Zend\InputFilter\InputFilter',
)
),
An example on how to use this can be found here on stackoverflow
To achieve what you want you most likely have to combine those two solutions. Not sure if it is the easiest way to do it, but it is definitely possible!
EDIT
For people who haven't setup validation at all yet:
For content validation in Apigility You have to use the zfcampus/zf-content-validation module and follow the documentation for configuration. This module allows you to configure your input-filters and validators in a input_filter_spec like you would normally do for form validation in ZF2. Here inside these input-filter config arrays you can use the configs that I referenced above.
So first properly install that module and once set-up you will be able to use these validation types in Apigility.
Related
I have been thinking about a good way to handle nested/complex values in POST requests to a apigility resource.
For example, an order might contain a collection of order items in a single POST requested that is used to create an order. Both, order and order-item do exist as a resource. However, I would very much like to have only one request that would create order and order item entities. Handling that in the resource is not a problem, but I wonder how you would configure that resource (let´s call it order-place) using the apigiliy UI - or, if at all impossible, using the configuration. Applying validators and filters is one of the key features of apigility, and i´d like to keep using that, even for complex request data.
And before you ask, using an underscore to separate the values scopes, for example order_comment and order_item_comment should not be an option.
Any ideas?:)
Addition: A sample json request payload could look like this:
{
"created_at": "2000-01-01",
"amount" : "5000.00",
"address" : {
"name": "some name",
"street": "some street"
...
},
"items" : [
{"productId":99,"qty":1}
...
]
}
Starting from Wilt's answer, I've found that the following code works as well:
# file path: /module/MyApi/config/module.config.php
// some other stuff
'MyApi\\V1\\Rest\\MyRestService\\Validator' => array(
'address' => array(
0 => array(
'name' => 'name',
'required' => true,
'filters' => array(),
'validators' => array(),
),
1 => array(
'name' => 'street',
'required' => true,
'filters' => array(),
'validators' => array(),
),
'type' => 'Zend\InputFilter\InputFilter'
),
'amount' => array(
'name' => 'amount',
'required' => true,
'filters' => array(),
'validators' => array()
)
The only problem I get is when address is passed as a field (string or numeric) rather then an array or object. In this case Apigility throws an exception:
Zend\InputFilter\Exception\InvalidArgumentException: Zend\InputFilter\BaseInputFilter::setData expects an array or Traversable argument; received string in /var/www/api/vendor/zendframework/zendframework/library/Zend/InputFilter/BaseInputFilter.php on line 175
Adding address as a further simple (required) field avoids the exception, but then Apigility doesn't see any difference whether we pass address as an array of name and street or a dummy string.
If you are using the ContentValidation module then you can configure an input filter for the nested resources by assigning it to a variable. Then you have to add a type key (essential otherwise reusing the filter won't work). Now you are able to use this variable in your input_filter_specs and you can reuse the whole filter inside another filter. So something like this in your config.php:
<?php
namespace Application;
// Your address config as if it was used independently
$addressInputFilter => array(
'name' => array(
'name' => 'name',
'required' => true,
'filters' => array(
//...
)
'validators' => array(
//...
)
),
'street' => array(
'name' => 'street',
'required' => true,
'filters' => array(
//...
)
'validators' => array(
//...
)
),
// 'type' key necessary for reusing this input filter in other configs
'type' => 'Zend\InputFilter\InputFilter'
),
'input_filter_specs' => array(
// The key for your address if you also want to be able to use it independently
'Application\InputFilter\Address'=> $addressInputFilter,
// The key and config for your other resource containing a nested address
'Application\InputFilter\ItemContainingAddress'=> array(
'address' => $addressInputFilter,
'amount' => array(
'name' => 'amount',
'required' => true,
'filters' => array(
//...
),
'validators' => array(
//...
)
)
//... your other fields
)
)
Is anyone familiar with the use of ZF2 regex validators within the factory pattern?
I have taken this code from various blogs and other stackoverflow questions, but it does not seem to work.
The addition of the regex validator blocks all changes to my form from updating the database - so the validator must be failing even when I insert a number.
However, when I check
$form -> getMessages();
I get an empty array. Any insight would be appreciated.
To illustrate I use a very simple regex that, as I understand it, would block any entry character that is not a number.
$inputFilter->add($factory->createInput(array(
'name' => 'Number',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'max' => 20,
),
),
),
array(
'name' => 'Regex',
'options' => array(
'pattern' => '/^[0-9]+$',
'messages' => array(
'Invalid input, only 0-9 characters allowed'
),
),
),
)));
At a glance, Regex validator should sit inside "validators" array...
i am trying to validate a user registration form in Zend Framework 2.
More specifically how to validate the email, ZF1 i could do:
$email->setValidators( array(new Zend_Validate_EmailAddress()) );
I'm wondering if i can just call something similar like this.
Also I'm wondering how to validate two fields that need to be the same like the password field and the password verification.
I guess that when i say if($form->isValid()).. this will check the getInputFilter() method for all validation.
I've been taking a look at ZfcUser module but, right now, i can't understand much since i don't have a full grasp on how ZF2 works
Any ideas, maybe a simple example?
thanks
Have you read the official tutorial to see how the new ZF2 Form component works?
At a very high level, you need a Form object and a Filter object working together. The Filter object is where you place your filters and validators. However, if you use a form element of type EmailAddress in your Form, then it will automatically add the correct validator. There is more information in the manual.
I recently did a webinar on forms for Zend which you should be able to find on this page.
i've figure it out.
the validators are multidimensional arrays and each array has a name and some options. It might be a bit wired in the beginning to notice it, but much configuration in zf2 is in this way
see an example for the password:
$inputFilter->add($factory->createInput([
'name' => 'password',
'required' => true,
'filters' => [ ['name' => 'StringTrim'], ],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'encoding' => 'UTF-8',
'min' => 6,
'max' => 128,
],
],
],
]));
$inputFilter->add($factory->createInput([
'name' => 'password_verify',
'required' => true,
'filters' => [ ['name' => 'StringTrim'], ],
'validators' => [
array(
'name' => 'StringLength',
'options' => array( 'min' => 6 ),
),
array(
'name' => 'identical',
'options' => array('token' => 'password' )
),
],
]));
note, in php 5.3 > an array could be written like array() or [], in the above example i mix them up for no particular reason.
I'm having problems implementing the IsImage File validator in a Form class in Zend Framework 2-beta5.
In general I'm having problems using any File validator in a Zend Form class in Zend framework 2.
I couldn't find any relevant documentation.
I found that for example Float validator that resides at Library/Zend/Validator
can be used with the following code:
$this->setInputFilter($inputFactory->createInputFilter(array(
'alcohol_vol' => array(
'name' => 'alcohol_vol',
'required' => true,
'validators' => array(
array(
'name' => 'Float',
),
),
),
)));
the IsImage file validator resides at /Library/Zend/Validator/File and can't find a way to use it. any information regarding the issue would be greatly appreciated.
thanks!
Kfir
Try to add this snippet under validators key, like this:
'validators' => array(
array(
'name' => '\Zend\Validator\File\IsImage',
'options' => array(
'break_chain_on_failure' => true,
),
),
),
But sometimes, depends on server configuration, IsImage might not working. Then use Extension validator instead:
'validators' => array(
array(
'name' => '\Zend\Validator\File\Extension',
'options' => array(
'extension' => array(
'png', 'jpeg', 'jpg',
),
'break_chain_on_failure' => true,
),
),
),
Upload file validate/filter should use Zend\File\Transfer but not Zend\Form
Try below way to add file validator
$fileTransfer = new Zend\File\Transfer\Transfer();
$fileTransfer->addValidators(array(
array('IsImage', true)
));
if($fileTransfer->isValid()){
$fileTransfer->receive();
}
I am trying to have a form with float number validation.
when validation works it won't let me click the submit button and will show the proper error message.
I am using zend framework 2 and in my Form I want to retrieve alcohol volume.
I'm trying to use the following code:
$this->add($factory->createElement(array(
'name' => 'alcohol_vol',
'attributes' => array(
'label' => 'alcohol vol%:',
'filters' => array('Float'),
'type' => 'text',
'required' => true,
),
)));
this doesn't do anything actually. it will pass validation if i enter regular text.
I also tried changing the type to 'Number' from 'text' but then it won't allow me to use floating number. it will allow only none-float numbers :)
There is no "Float" filter in ZF2, I guess may you want is "Float" Validator, Float Validator could be add into ZF2 form like this:
$this->add($factory->createElement(array(
'name' => 'alcohol_vol',
'attributes' => array(
'label' => 'alcohol vol%:',
'type' => 'text',
),
)));
$factory = new Zend\InputFilter\Factory();
$this->setInputFilter($factory->createInputFilter(array(
'alcohol_vol' => array(
'name' => 'alcohol_vol',
'required' => true,
'validators' => array(
array(
'name' => 'Float',
),
),
),
)));
Then you should validate form in controller, above validators should still set into form. If input not float, the input element will have invalidate messages:
$form->setData($userInputData);
if (!$form->isValid()) {
$inputFilter = $form->getInputFilter();
$invalids = $inputFilter->getInvalidInput();
var_dump($invalids);
// output: 'abc' does not appear to be a float
}
I think you can use this filter
new Zend\I18n\Filter\NumberFormat("en_US", NumberFormatter::TYPE_DOUBLE);
I recommend the Zend\I18n\Validator\Float class. Example usage:
$floatInput = new Input('myFloatField');
$floatInput->getValidatorChain()
->attach(new \Zend\I18n\Validator\Float());
See:
http://framework.zend.com/manual/2.3/en/modules/zend.input-filter.intro.html
http://framework.zend.com/manual/2.0/en/modules/zend.validator.set.html#validating-digits