zf2 formFilter regex howto - zend-framework2

Using zendframework v2, I have run into a problem with a regex validator on a field created by the Form factory. All other fields (using the same pattern) work without a problem.
Any tips, or pointers is appreciated.
$inputFilter->add($factory->createInput([
'name' => 'organizationName',
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array(
'messages' => array(
\Zend\Validator\NotEmpty::IS_EMPTY => 'Organization name field is empty',
),
),
),
array(
'name' => 'Regex',
'options' => array(
'pattern' => '/^[a-z0-9 &-_\.,#]{3,25}$/i',
'messages' => array(
\Zend\Validator\Regex::INVALID => 'Invalid input, only a-z, 0-9 & - _ . characters allowed',
),
),
),
array (
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => '2',
'max' => '25',
'messages' => array(
\Zend\Validator\StringLength::TOO_SHORT => 'Organization name field must be at least 8 characters in length',
\Zend\Validator\StringLength::TOO_LONG => 'Organization name field must be no longer than 25 characters in length',
),
),
),
),
]));
Additional details:
I am using the ZF2 to generate a form, I also create a validation filter and then use the controller to handle proper form submissions.
The problem I am having is with the above inputFilter object that handles the "organizationName" regex filter.
It seems that although the regex patter I use both in the form definition and the input filter of [a-z0-9 &-_.,#]{3,25} does not handle the string Intl. Widgets Inc. even though I do not get an error message from $form->getMessages() etc.
Color me stumpted

That's because your regexp does match Intl. Widgets Inc. : http://rubular.com/r/oPbk2cdarB

Related

zf2 default validation messages not overriding

$inputFilter->add(array(
'name' => 'nightCharges',
'required' => FALSE,
'filters' => array(
array('name' => 'Digits'),
),
'validators' => array(
array(
'name' => 'GreaterThan',
'options' => array(
'min' => 1,
'messages' => array(
\Zend\Validator\GreaterThan::NOT_GREATER => 'My message',
),
),
),
),
));
Above is my code snippet for validation in this case for 'check box'. If I set 'required' to "true" and submit empty form, it shows me the default 'Value is required and can't be empty' message and if I set 'required' to 'false' it does't show me any error at all. Even if I submit non digit value it doesn't show me actual error message.
Where am I making mistake?
Actually I was working on 'Please accept the terms & conditions' check box.
Rather than using the GreaterThan validator, try using Identical to ensure the value can't be anything other than 1.
'validators' => array(
array(
'name' => 'Identical',
'options' => array(
'token' => '1',
'messages' => array(
Identical::NOT_SAME => 'Please accept the terms & conditions.',
),
),
),
),

Zend Form Validation set error messages

I have setup a form along with filters and validators which seem to work correctly.
However, I can not seem to get custom error messages to work. So far I have tried.
$inputFilter->add(array(
'name' => 'message',
'required' => TRUE,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'messages' => array(
NotEmpty::IS_EMPTY => "You must specify your message",
),
),
),
));
All I get is the standard validation error message 'Value is required and can't be empty'
Please can someone point me in the right direction, many thanks.
You need to put your messages stack into options top key in validator configuration like below:
Wrong:
'validators' => array(
array(
'name' => 'NotEmpty',
'messages' => array(
NotEmpty::IS_EMPTY => "You must specify your message",
),
),
),
Correct:
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array(
'messages' => array(
NotEmpty::IS_EMPTY => "You must specify your message",
),
),
),
),

Zend framework 2 translate Image captcha messages

I have this Image captcha thats is working correctly, but I can't get the "badCaptcha" validation error translated.
I have the key Captcha value is wrong translated in my .po file with PoEdit.
This is my CAPTCHA form element:
$this->form->add(array(
'name' => 'captcha',
'type' => 'Zend\Form\Element\Captcha',
'options' => array(
'captcha' => new \Zend\Captcha\Image(array(
'imgDir' => './public/assets/images/captcha',
'ImgUrl' => '/assets/images/captcha',
'width' => 330,
'height' => 90,
'wordlen' => 3,
'dotNoiseLevel' => 30,
'lineNoiseLevel' => 3,
'font' => './data/captcha/font/monofont.ttf',
'fontSize' => 52,
'expiration' => 600,
)),
'messages' => array(
'badCaptcha' => $this->getTranslatorHelper()->translate('Captcha value is wrong', 'csnuser'),
),
),
));
PS: $this->getTranslatorHelper() retrieves the MvcTranslator service.
This is all wrong...ZF2 documentation in this topic is at least innacurate.
You may activate this very basic function this way:
In your Application (yes, I'm using Skeleton App) module config file (module.config.php)
...
...
'translator' => array(
'locale' => 'xx_XX', //Or whatever you want
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
// Add this new file pattern
array(
'type' => 'phparray',
//You get this translated files from vendor/zendframework/zendframework/resources/languages
'base_dir' => __DIR__ . '/../language/validation',
//You may rename it to xx_XX.php for the pattern to match!
'pattern' => '%s.php',
),
...
...
...
After that, you may create Application module onBootstrap event listener in Module.php file, like this:
public function onBootstrap(MvcEvent $event)
{
...
...
\Zend\Validator\AbstractValidator::setDefaultTranslator($event->getApplication()->getServiceManager()->get('MvcTranslator'));
...
...
}
This way I got Captcha value is wrong translated!
ZF2 has already translate all forms messages zend_validate.php and captacha_validate.php are already translated them
you can find them here :
vendor\zendframework\zendframework\resources\languages\fr
Copy this files into your application langage folder and call them into your config
'translator' => array(
'locale' => 'fr_FR',
'translation_files' => array(
array(
'type' => 'phpArray',
'filename' => 'resources/languages/fr.php'
),
),
),
for example
You can have both php translation file AND po file.
EDIT :
'translator' => array(
'locale' => 'fr_FR',
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo', //<-%s is important
),
array(
'type' => 'phpArray',
'base_dir' => './module/Application/language/Zend_Validate/',
'pattern' => '%s-Zend_Validate.php',
),
),
),
When you have multiple lang to handle you have to load different file according to the lang choosen. %s take 'locale'.
Check if it's your problem :)
No renaming nescecary:
'pattern' => '%2.2s/Zend_Validate.php'

ZF2 - Navigation routing with language

In ZF2 I have two languages English and Chinese. Every route starts with language like:
'about' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/[:lang]/about',
'constraints' => array(
'lang' => '(en|zh)?',
),
'defaults' => array(
'controller' => 'Application\Controller\About',
'action' => 'index',
'lang' => 'en',
),
),
),
I have already translated label with setTranslator, but I do not know how I can add language parameter to the route. It seems to me like this problem Translation of URI segments in ZF2
'navigation' => array(
'default' => array(
array(
'label' => 'About',
'route' => 'about',
'class' => 'top-level',
),
),
Or is there better way how to handle this for example prepend language to every url like this How to prepend language to every url in Zend Framework
In general, there is a params key in the navigation to supply route parameters. It must contain an array of all values used in the route.
An example, for the route foo[/:bar] you can have this navigation configuration:
array(
'label' => 'Foo',
'route' => 'foo-bar',
'params' => array('bar => 'baz'),
),
In your translation case, provide a params key called lang and than one will be used.
However you probably want to use the route match parameter for the language. If you are on the page from language zh then the parameter is automatically zh. Then you can use the use_route_match.
array(
'label' => 'About',
'route' => 'about',
'use_route_match' => true,
),

zf2 router: One module makes the router unable to find another module. How can I make both work?

We're just starting out with zf2, so someone else made a Thumbnail server module, and then I added a Lookup server module. I call these servers because they're both RESTful apis. Initially they seemed to work together, but someone made some changes to my module, and now the Thumbnail server won't work unless Lookup is removed from the application.config.php list of modules. The Lookup server works regardless. Looking over the code, I don't see how the changes made to Lookup would affect Thumbnail. The error I'm getting looks like this:
<h1>A 404 error occurred</h1>
<h2>Page not found.</h2>
<p>The requested controller was unable to dispatch the request.</p>
<dl>
<dt>Controller:</dt>
<dd>Lookup\Controller\Lookup</dd>
</dl>
Here's what application.config.php looks like:
<?php
return array(
'modules' => array(
'Application',
'SanRestful',
'Album',
'AlbumRest',
'Thumbnail',
'Lookup',
'AP_XmlStrategy',
),
'module_listener_options' => array(
'config_glob_paths' => array(
'config/autoload/{,*.}{global,local}.php',
'config/autoload/{,*.}' . (getenv('APPLICATION_ENV') ?: 'production') . '.php',
),
'module_paths' => array(
'./module',
'./vendor',
),
),
);
As you can see, there's the initial Album module, and a few other experimental ones. My Lookup module uses the excellent AP_XmlStrategy module by Allessandro Pietrobelli.
Below is the Thumbnail module.config.php. It has a constraint that's probably not being used because there are no arguments called "id", but that shouldn't mess things up, should it?
<?php
return array(
'controllers' => array(
'invokables' => array(
'Thumbnail\Controller\Thumbnail' => 'Thumbnail\Controller\ThumbnailController',
),
),
// The following section is new and should be added to your file
'router' => array(
'routes' => array(
'thumbnail' => array(
'type' => 'segment',
'options' => array(
'route' => '/thumbnail[/:action][/:output]',
'constraints' => array(
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Thumbnail\Controller\Thumbnail',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'thumbnail' => __DIR__ . '/../view',
),
),
);
And the Lookup module.config.php, with identifiers obfuscated:
<?php
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'pgsql:dbname=<dbname>;host=<host>;port=<port>',
'username' => '<username>',
'password' => '<password>',
),
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter'
=> 'Zend\Db\Adapter\AdapterServiceFactory',
),
'aliases' => array(
'db' => 'Zend\Db\Adapter\Adapter',
),
),
'controllers' => array(
'invokables' => array(
'Lookup\Controller\Lookup' => 'Lookup\Controller\LookupController',
),
),
// The following section is new and should be added to your file
'router' => array(
'routes' => array(
'lookup' => array(
'type' => 'segment',
'options' => array(
'route' => '[/:action][/:version][/:resource][/:code][/:resource_xref]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'version' => '[a-zA-Z][a-zA-Z0-9_-]*',
'resource' => '[a-zA-Z][a-zA-Z0-9_-|\.]*',
'code' => '[a-zA-Z][a-zA-Z0-9_-]*',
'resource_xref' => '[a-zA-Z][a-zA-Z0-9_-|\.]*',
),
'defaults' => array(
'controller' => 'Lookup\Controller\Lookup',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'lookup' => __DIR__ . '/../view',
),
'strategies' => array(
'ViewJsonStrategy',
'ViewXmlStrategy',
),
),
);
Are there any obvious mistakes here that I'm missing?
Requests can be matched by multiple routes. An example: the url /foo can be matched by a literal route /foo and also the route [/:action]. To distinguish the two routes, the order how you configure them matters.
What happens, the routes are matched in LIFO order, so the last route must be the most explicit. In the "/foo" example, this config will match the literal:
'router' => array(
'routes' => array(
'test1' => array(
'type' => 'segment',
'options' => array(
'route' => '[/:action]',
'defaults' => array(
//
),
),
),
'test2' => array(
'type' => 'literal',
'options' => array(
'route' => '/foo',
'defaults' => array(
//
),
),
),
),
),
However, in the below config, the literal will never be matched, because [/:action] is a possible match for /foo.
'router' => array(
'routes' => array(
'test2' => array(
'type' => 'literal',
'options' => array(
'route' => '/foo',
'defaults' => array(
//
),
),
),
'test1' => array(
'type' => 'segment',
'options' => array(
'route' => '[/:action]',
'defaults' => array(
//
),
),
),
),
),
Now take a look at your two modules. The first (Thumbnail) has a route /thumbnail[/:action][/:output]. it starts with a literal part. Then your second module (Lookup) has a route [/:action][/:version][/:resource][/:code][/:resource_xref].
Now if you get back to the LIFO order, any route starting with /thumbnail will match already at the Lookup route.
Solution
There are two options. First is to swap the order of the modules. This is always an important order if you have inter-dependent relations between modules. Load Lookup first and then Thumnnail, so the thumbnail route is put later in the config. Thus, it matches first. Thus, your app works again.
Then there is the second solution (and imho, the better). You have a "one route to rule them all" in the Lookup, which is not a really good practice. You can get into trouble exactly like you are now, having no idea what went wrong. Thus, specify as much as possible in your routes. Make the first part of the Lookup also literal (is /lookup[/:action][/:version][/:resource][/:code][/:resource_xref] not an option?). Or remove action as parameter and make those literal:
'router' => array(
'routes' => array(
'view' => array(
'type' => 'segemnt',
'options' => array(
'route' => '/view[/:version][/:resource][/:code][/:resource_xref]',
'defaults' => array(
'action' => 'view',
//
),
),
),
'create' => array(
'type' => 'segment',
'options' => array(
'route' => '/create[/:version][/:resource][/:code][/:resource_xref]',
'defaults' => array(
'action' => 'create',
//
),
),
),
'update' => array(
'type' => 'segment',
'options' => array(
'route' => '/update[/:version][/:resource][/:code][/:resource_xref]',
'defaults' => array(
'action' => 'update',
//
),
),
),
// And so on
),
),
This way, your lookup module has a fixed starting point and matches only if those first parts are in the request uri. Then your /thumbnail[/:action][/:output] is completely decoupled from the Lookup routes.

Resources