Zend Form Validation set error messages - zend-framework2

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",
),
),
),
),

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.',
),
),
),
),

zf2 formFilter regex howto

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

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.

404 error, Zend Framework 2 The requested URL could not be matched by routing

I'm getting:
A 404 error occurred
Page not found. The requested URL could not be matched by routing.
My module.config.php file is:
'router' => array(
'router' => array(
'Test' => array(
'type' => 'Segment',
'options' => array(
//http://localhost/Test/Test
'route' => '/Test[/[:action]]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Test\Controller\Test',
'action' => 'Test'
),
),
),
),
),
help please, i am new in Zend Framework 2 !
You should use configuration like Application module in ZendSkeletonApplication:
'router' => array(
'routes' => array(
'test' => array(
'type' => 'Literal',
'options' => array(
'route' => '/book',
'defaults' => array(
'__NAMESPACE__' => 'Test\Controller',
'controller' => 'Test',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
),
),
You just add the following code:
'test' => array(
'type' => 'Segment',
'options' => array(
'route' => '[/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]*',
),
'defaults' => array(
'__NAMESPACE__' => 'Test\Controller',
'controller' => 'Test',
'action' => 'index',
),
),
),
add this code to 'child-routes' key and after that you'll access to url: localhost/:controller_name/:action_name/:id (example : http://zf.dev/test/index or http://zf.dev/test/add/1). And now it's work!
This code can fix error 404 for tutorial in zf2 documentation.
You have a typo, try this:
'router' => array(
'routes' => array(
Routes rather than router twice..
Achieve fix it, I was missing the letter "d", was thus: Zend \ Loader \ StandarAutoloader I added the "d": Zend \ Loader \ StandardAutoloader. Greetings Friends. TIP: Zend Studio 10 and his version de ZF2 run perfect for this moment !
Please check the .htaccess file and index.php files. If these are exist in public folder means, you have to use the url as
http://localhost/public/Test/Test.
Your codes are almost right. Andrew has guided you well. Let me know your response.
1.You should check also application.config.php
and add your module name into RETURN array.
return array(
'modules' => array(
'Application',
'your_module',
.....
),
2.If Doesn't.Check route array in module.config.php
I will suggest also check the data folder that has cached config files, config files being cached in dev install also may cause this issue.
delete files inside data/cache and try.
PS: if you are just starting try with blog module on zend site it is for beginners and more updated with new versions.
https://framework.zend.com/manual/2.4/en/in-depth-guide/first-module.html

Zend\Navigation breadcrumb doesn't find active elements

i've got my navigation running and all links are working fine. Rendering the Navigation using $this->navigation($nav)->menu() will display an unordered list and all links are working.
Additionally the active link there is working, too. The active element has class="active" as an attribute.
Rendering the same navigation, only as a bradcrumb $this->navigation($nav)->breadcrumbs() doesn't render me anything. This MAY be due to my navigation only being one level deep for now, but imo the first level should still be rendered.
Using super modern die()-debugging i found out that nothing get's rendered because the findActive() of the viewHelper doesn't find an active element and therefore returns an empty string.
Any thoughts on where my error may be located? Any insight will be greatly appreciated. Here's my code so far:
'navigation' => array(
'default' => array(
'biete' => array(
'label' => 'Biete',
'route' => 'biete',
),
'suche' => array(
'label' => 'Suche',
'route' => 'suche',
),
'administration' => array(
'label' => 'Administration',
'route' => 'admin'
),
'dashboard' => array(
'label' => 'Meine Artikel',
'route' => 'dashboard'
),
'login' => array(
'label' => 'Anmelden',
'route' => 'duituser/login'
),
'logout' => array(
'label' => 'Abmelden',
'route' => 'duituser/logout'
)
),
),
'service_manager' => array(
'factories' => array(
'translator' => 'Zend\I18n\Translator\TranslatorServiceFactory',
'navigation' => 'Zend\Navigation\Service\DefaultNavigationFactory',
),
),
And the view Parts located in my layout.phtml
<?php echo $this->navigation('navigation')->menu(); ?>
<?php echo $this->navigation('navigation')->breadcrumbs(); ?>
Thanks again in advance.
I had a play with the Navigation classes/helper - it seems that breadcrumbs are rendered (in the example below) when the 'playground' route is matched. However by adding 'active' => true to my default route means it will always be rendered by the breadcrumb helper.
'navigation' => array(
'default' => array(
'test' => array(
'label' => 'Home',
'route' => 'test',
'active' => true,
'pages' => array(
'playground' => array(
'label' => 'Playground',
'route' => 'playground',
),
),
),
),
),
In addition to the answer of DrBeza, here is what helped me. The problem was that the Breadcrumb-Navigation only got rendered once we hit the second level. But you can obviously change that setting by calling the following:
$this->navigation('navigation')->breadcrumbs()->setMinDepth(0);
To me, this is all that was needed. As DrBeza pointed out however in some cases this may not be enough.
In my case helps only this this:
$this->navigation('navigation')->breadcrumbs()->render('navigation');
The strange is, that it's required only if $this->navigation('navigation')->menu() is called before, because breadcrumbs are not rendered.

Resources