I have application that runs with different languages. The custom labels, header $this->translate('message') are working perfectly with any problem. I just face problem with translating zend error Message form. Here is what I added it in module.config.php. Could any one help me to display error message form in different languages.
'translator' => array(
'locale' => 'pl',
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
array(
'type' => 'phpArray',
'base_dir' => 'vendor/zendframework/zend-i18n-resources/languages',
'pattern' => '%s/Zend_Captcha.php',
'text_domain' => 'formvalidation',
),
array(
'type' => 'phpArray',
'base_dir' => 'vendor/zendframework/zend-i18n-resources/languages',
'pattern' => '%s/Zend_Validate.php',
'text_domain' => 'formvalidation',
),
),
),
This is how I do it within the getInputFilter form function. This way I can retrieve the string in Poedit and proceed with the translations:
public function getInputFilter() {
if (!$this->filter) {
$inputFilter = new InputFilter();
$factory = new InputFactory ();
$inputFilter->add($factory->createInput(array(
'name' => 'email',
'filters' => array(
array(
'name' => 'StripTags'
),
array(
'name' => 'StringTrim'
)
),
'validators' => array(
array(
'name' => 'EmailAddress',
'options' => array(
'messages' => array(
'emailAddressInvalidFormat' => _('Email address format is not invalid')
)
)
),
array(
'name' => 'NotEmpty',
'options' => array(
'messages' => array(
'isEmpty' => _('Email address is required')
)
)
),
array(
'name' => 'StringLength',
'options' => array(
'min'=>6,
'max'=>128,
'messages' => array(
\Zend\Validator\StringLength::TOO_LONG => _('Invalid length for this field')
)
)
)
)
)));
$this->filter = $inputFilter;
}
return $this->filter;
}
Related
I am creating ZF2 email address validator via factory that has 2 parts, one checks if emaill is already in DB, two: validate the email.
Prblem is that my NoObjectExists validator works just fine, but the acatual Email address validator does not (validator recognises "dsfsfhsadjkfnaskl" as valid email). Here is my code, maybe you guys can spot what is wrong with it?
$factory = new \Zend\InputFilter\Factory();
$input = $factory->createInput(array(
'name' => 'email',
'required' => false,
'filters' => array(
0 => array(
'name' => 'Zend\Filter\StringTrim',
'options' => array(),
),
),
'validators' => array(
0 => array(
'name' => '\DoctrineModule\Validator\NoObjectExists',
'options' => array(
'object_repository' => $this,
'fields' => array('email'),
),
1 => array(
'name' => '\Zend\Validator\EmailAddress',
'options' => array(
'allow' => \Zend\Validator\Hostname::ALLOW_DNS,
'domain' => true,
),
),
),
),
));
return $input;
You have an error in your array nesting. You aren't closing off the containing the NoObjectExists validator so the Email validator is nested inside.
Try the following:
$factory = new \Zend\InputFilter\Factory();
$input = $factory->createInput(array(
'name' => 'email',
'required' => false,
'filters' => array(
0 => array(
'name' => 'Zend\Filter\StringTrim',
'options' => array(),
),
),
'validators' => array(
0 => array(
'name' => '\DoctrineModule\Validator\NoObjectExists',
'options' => array(
'object_repository' => $this,
'fields' => array('email'),
),
),
1 => array(
'name' => '\Zend\Validator\EmailAddress',
'options' => array(
'allow' => \Zend\Validator\Hostname::ALLOW_DNS,
'domain' => true,
),
),
),
));
return $input;
I have a custom validator using $context that has been working for over a year.
The $context contains all posted parameters except for "bar" which is an empty array although it is posted as bar[0][description]. The array used to contain one or more arrays with key-value-pairs.
This seems to be the case since updating from version 2.3.2 to 2.5.1
I can't even check the 2.5 documentation since it's not available, Google didn't turn up anything close to the issue, ... was the behaviour changed or is this a bug?
Edit:
In .../Lorem/Form/FooForm.php I include a fieldset:
public function __construct() {
// ...
$this->add(array(
'type' => 'Collection',
'name' => 'bar',
'options' => array(
'label'=> '',
'count' => 1,
'should_create_template' => TRUE,
'allow_add' => TRUE,
'use_as_base_fieldset' => TRUE,
'target_element' => array(
'type' => 'Lorem\Fieldset\BarFieldset'
)
)
));
}
In .../Lorem/Fieldset/BarFieldset.php I have:
public function __construct() {
parent::__construct('bar');
$this->setHydrator(new ReflectionHydrator())
->setObject(new Bar());
$this->add(array(
'name' => 'description',
'type' => 'Textarea',
'attributes' => array(
'rows' => 3,
'cols' => 40,
),
));
$this->add(array(
'name' => 'amount',
'attributes' => array(
'type' => 'Text',
'class' => 'input-bar-amount',
'maxlength' => 9,
),
));
// ...
}
public function getInputFilterSpecification()
{
return array(
'description' => array(
'required' => TRUE,
'filters' => array(
array('name' => 'StripTags'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'break_chain_on_failure' => TRUE,
'options' => array(
'messages' => array(
'isEmpty' => 'Please enter a description.',
),
),
),
),
),
'amount' => array(
'required' => TRUE,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'break_chain_on_failure' => TRUE,
'options' => array(
'messages' => array(
'isEmpty' => 'Please enter amount.',
),
),
),
array(
'name' => 'Float',
'break_chain_on_failure' => TRUE,
'options' => array(
'locale' => 'de',
'messages' => array(
'floatInvalid' => 'Invalid input. String, Integer oder Float expected.',
'notFloat' => 'Input ist not a floating point number.',
),
),
),
array(
'name' => 'Between',
'break_chain_on_failure' => TRUE,
'options' => array(
'min' => -1000000,
'max' => 1000000,
'messages' => array(
'notBetween' => "Only values between '%min%' and '%max%' EUR are allowed.",
'notBetweenStrict' => "Only values between '%min%' and '%max%' EUR are allowed.",
),
),
),
),
),
// ...
);
}
I'm trying to create a simple application with Zend Framework 2 and now stacked at the point of adding comments form.
I have two modules "Book" and "Comment". I want to show a form for adding comments that is disposed in module "Comment" from "Books" module controller.
The problem appears when I'm trying to open forms tag.
I'm having this error : " Fatal error: Call to undefined method Comment\Form\CommentForm::openTag()".
I tried to check $this->addComment - with var_dump and everything looks great.
Can anybody help me to solve this problem ?
<div class="row">
<div class="col-xs-12 commentBlock">
<?php
if($this->addComment){
$this->addComment->prepare();
$commentFieldset = $this->addComment->get('comment');
print $this->addComment()->openTag($this->addComment);
}
?>
</div>
</div>
Here is 'Comment' module files :
Comment\Form\CommentFieldset
<?php
namespace Comment\Form;
use Comment\Entity\Comment;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
use Zend\Stdlib\Hydrator\ClassMethods as ClassMethodsHydrator;
class CommentFieldset extends Fieldset implements InputFilterProviderInterface
{
public function __construct()
{
parent::__construct('comment');
$this->add(
array(
'name' => 'commentTitle',
'attributes' => array(
// 'required' => 'required',
'class' => 'form-controll',
'placeholder' => 'Введите заголовок комментария'
),
'options' => array(
'label' => 'Заголовок комментария',
'label_attributes' => array(
'class' => 'text-center col-sm-3 control-label',
),
),
)
);
$this->add(
array(
'name' => 'commentText',
'type' => 'Zend\Form\Element\Textarea',
'attributes' => array(
'required' => 'required',
'class' => 'form=-controll',
'palceholder' => 'Введите текст комментария',
),
'options' => array(
'label' => 'Текст комментария',
'label_attributes' => array(
'class' => 'text-center col-sm-3 control-label',
),
),
)
);
$this->add(
array(
'name' => 'commentType',
'type' => 'Zend\Form\Element\Radio',
'attributes' => array(
'required' => 'required',
),
'options' => array(
'label' => 'Тип комментария',
'label_attributes' => array(
'class' => 'text-center col-sm-3 control-label',
),
'value_options' => array(
'positive' => 'postive',
'neutral' => 'neutral',
'negative' => 'negative',
),
),
)
);
}
public function getInputFilterSpecification()
{
return array(
'commentTitle' => array(
'required' => FALSE,
'filters' => array(
array(
'name' => 'Zend\Filter\StripTags',
),
array(
'name' => 'Zend\Filter\HtmlEntities'
),
array(
'name' => 'Zend\Filter\StringTrim',
),
),
'validators' => array(
array(
'name' => 'Zend\Validator\StringLength',
'options' => array(
'min' => 1,
'max' => 250,
),
),
),
),
'commentText' => array(
'required' => TRUE,
'filters' => array(
array(
'name' => 'Zend\Filter\StripTags',
),
array(
'name' => 'Zend\Filter\HtmlEntities'
),
array(
'name' => 'Zend\Filter\StringTrim',
),
),
'validators' => array(
array(
'name' => '\Zend\Validator\StringLength',
'options' => array(
'min' => 1,
'max' => 1000,
),
),
),
),
'commentType' => array(
'required' => true,
'validators' => array(
array(
'name' => 'Zend\Validator\InArray',
'options' => array(
'haystack' => array(
'positive',
'neutral',
'negative',
),
'strict' =>\Zend\Validator\InArray::COMPARE_STRICT,
),
),
),
),
);
}
}
Comment\Form\CommentFieldset
<?php
namespace Comment\Form;
use Zend\Form\Form;
use Zend\InputFilter\InputFilter;
use Zend\Stdlib\Hydrator\ClassMethods as ClassMethodsHydrator;
class CommentForm extends Form
{
public function __construct()
{
parent::__construct('comment');
$this
->setAttribute('method', 'POST')
->setHydrator(new ClassMethodsHydrator())
->setInputFilter(new InputFilter())
;
$this->add(
array(
'type' => 'Comment\Form\CommentFieldset',
'options' => array(
'use_as_base_fieldset' => true,
),
)
);
$this->add(
array(
'name' => 'csrf',
'type' => 'Zend\Form\Element\Csrf',
)
);
$this->add(
array(
'name' => 'captcha',
'type' => 'Zend\Form\Element\Captcha',
'options' => array(
'label' => 'А вы точно-приточно не робот ? ',
'captcha' => new \Zend\Captcha\Figlet(),
'attributes' => array(
'required' => true,
)
),
)
);
$this->add(
array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Добавить комментарий',
'class' => 'bigSubmit btn btn-pink',
),
)
);
$this->setValidationGroup(
array(
'csrf',
'captcha',
'comment' => array(
'commentTitle',
'commentText',
'commentType',
),
)
);
}
}
Comment\View\Helper\DisplayAddCommentForm
<?php
namespace Comment\View\Helper;
use Zend\Form\View\Helper\AbstractHelper;
class DisplayAddCommentForm extends AbstractHelper
{
public function __invoke()
{
return new \Comment\Form\CommentForm();
}
}
Book\Controller\BookController
<?php
namespace Book\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\View\Model\JsonModel;
use Comment\Form\CommentForm;
class BookController extends AbstractActionController
{
protected $bookModel;
protected $commentsModel;
public function showAction()
{
$isbn = $this->params()->fromRoute('num');
$book = $this->bookModel->getU(array($isbn));
$comments = $this->commentsModel->getBookComments(array($isbn));
if($_SESSION['user']){
$commentForm = new CommentForm();
} else {
$commentForm = NULL;
}
return new ViewModel(
array(
'book' => $book,
'comments' => $comments,
'addComment' => $commentForm,
)
);
}
**************
}
openTag() is method from form view helper not from your helper. In your view script change this line : print $this->addComment()->openTag($this->addComment); to this one print $this->form()->openTag($this->addComment);
I used authentication in zend module but when i render it gives me error like
Zend\View\Renderer\PhpRenderer::render: Unable to render template "calendar/index/login"; resolver could not resolve to a files
here is my module.config.php:
<?php
return array(
'controllers' => array(
'invokables' => array(
'Calendar\Controller\Index' => 'Calendar\Controller\IndexController',
'Calendar\Controller\User' => 'Calendar\Controller\UserController',
'Calendar\Controller\Calendar' => 'Calendar\Controller\CalendarController',
'Calendar\Controller\Event' => 'Calendar\Controller\EventController'
),
),
'router' => array(
'routes' => array(
/*###############*/
//index
'admin_index' => array(
'type'=>'segment',
'options' => array(
'route'=>'/calendar/admin[/]',
'defaults'=>array('controller'=>'Calendar\Controller\Index','action'=>'index')
)
),
//login
'admin_login' => array(
'type'=>'literal',
'options' => array(
'route'=>'/calendar/admin/login',
'defaults'=>array('controller'=>'Calendar\Controller\Index','action'=>'login')
)
),
//logout
'admin_logout' => array(
'type'=>'literal',
'options' => array(
'route'=>'/calendar/admin/logout',
'defaults'=>array('controller'=>'Calendar\Controller\Index','action'=>'logout')
)
),
//user index
'admin_user' => array(
'type'=>'segment',
'options' => array(
'route'=>'/calendar/admin/user[/]',
'defaults'=>array('controller'=>'Calendar\Controller\User','action'=>'index')
)
),
//user add
'admin_user_add' => array(
'type'=>'segment',
'options' => array(
'route'=>'/calendar/admin/user/add[/]',
'defaults'=>array('controller'=>'Calendar\Controller\User','action'=>'add')
)
),
//user edit
'admin_user_edit' => array(
'type'=>'segment',
'options' => array(
'route' =>'/calendar/admin/user/edit[/:id]',
'constraints' => array(
'action' => 'edit',
'id' => '[a-zA-Z0-9_-]+',
),
'defaults'=>array('controller'=>'Calendar\Controller\User','action'=>'edit')
)
),
//user profile
'admin_profile' => array(
'type'=>'segment',
'options' => array(
'route'=>'/calendar/admin/profile[/]',
'defaults'=>array('controller'=>'Calendar\Controller\Index','action'=>'profile')
)
),
'calendar' => array(
'type' => 'segment',
'options' => array(
'route' => '/calendar[/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Calendar\Controller\Calendar',
'action' => 'index',
),
),
),
'event' => array(
'type' => 'segment',
'options' => array(
'route' => '/event[/:action][/:id][/:unixTime][/:allDay]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
'unixTime' => '[0-9]+',
'allDay' => '0|1',
),
'defaults' => array(
'controller' => 'Calendar\Controller\Event',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'calendar' => __DIR__ . '/../view',
),
),
);
and here is my controller action:
public function loginAction(){
//$this->layout('layout/login-layout.phtml');
$login_error=false;
$loginForm = new LoginForm();
if ($this->request->isPost())
{
$loginForm->setData($this->request->getPost());
if ($loginForm->isValid())
{
//die("dgdgdgdgdgdgdgdg");
$data = $loginForm->getData();
$authService = $this->getServiceLocator()
->get('doctrine.authenticationservice.odm_default');
$adapter = $authService->getAdapter();
$adapter->setIdentityValue($data['username']);
$adapter->setCredentialValue(md5($data['password']));
$authResult = $authService->authenticate();
//for disable authentication comment here////////////////////////////
if ($authResult->isValid()) {
$identity = $authResult->getIdentity();
//$authService->getStorage()->write($identity);
$this->redirect()->toRoute('admin_index');
}
else {
$identity =false;
$login_error= true;
}
//for disable authentication comment here////////////////////////////
}
}
//
return new ViewModel(array(
'loginForm' => $loginForm,
'login_error' => $login_error,
));
}
That error occurs when you forgot to make the actual for your view. You need to create that template and place it in the appropriate view directory. Then this error should go away.
I have a requirement of rendering and processing the same form again if user check a select box. I looked into form collections but it didn't exactly access my problem because I don't need to render a set of fields instead my requirement is to render the complete form again. So what I added another function getClone($prefix) to get the clone of form which returns me the clone of form object after adding a prefix in the name of form. Like this
<?php
namespace Company\Form;
use Zend\Form\Form;
use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
class CompanyAddress extends Form implements InputFilterAwareInterface {
protected $inputFilter;
public function __construct($countries, $name = 'null') {
parent::__construct('company_address');
$this->setAttribute('method', 'post');
$this->setAttribute('id', 'company_address');
$this->add(array(
'name' => 'street_1',
'attributes' => array(
'id' => 'street_1',
'type' => 'text',
),
'options' => array(
'label' => 'Street *',
)
));
$this->add(array(
'name' => 'street_2',
'attributes' => array(
'id' => 'street_2',
'type' => 'text',
),
'options' => array(
'label' => 'Street 2',
)
));
$this->add(array(
'name' => 'country_id',
'type' => 'Zend\Form\Element\Select',
'attributes' => array(
'id' => 'country_id',
),
'options' => array(
'label' => 'Country',
'value_options' => $countries
)
));
$this->add(array(
'name' => 'city_id',
'type' => 'Zend\Form\Element\Select',
'attributes' => array(
'id' => 'city_id',
),
'options' => array(
'label' => 'City ',
'value_options' => array()
)
));
$this->add(array(
'name' => 'zip',
'attributes' => array(
'id' => 'zip',
'type' => 'text',
),
'options' => array(
'label' => 'ZIP',
'value_options' => array()
)
));
$this->add(array(
'name' => 'address_type',
'type' => 'Zend\Form\Element\Select',
'attributes' => array(
'id' => 'zip',
),
'options' => array(
'label' => 'Type',
'value_options' => array(
'' => 'Select Type',
'default' => 'Default',
'invoice' => 'Invoice',
'both' => 'Both',
)
)
));
}
public function getClone($prefix){
$form = clone $this;
foreach($form->getElements() as $element){
$name = $element->getName();
$element->setName("$prefix[$name]");
}
return $form;
}
public function getInputFilter() {
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'street_1',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array('message' => 'Street cannot be empty'),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'street_2',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'city_id',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array('message' => 'City cannot be empty'),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'country_id',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array('message' => 'Country cannot be empty'),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'zip',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array('message' => 'ZIP cannot be empty'),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'address_type',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array('message' => 'Address Type cannot be empty'),
),
),
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
and than in my action I did this
public function testAction() {
$countries = $this->getServiceLocator()->get('Country')->getSelect();
$companyAddressForm = new CompanyAddressForm($countries);
$clone = $companyAddressForm->getClone('address2');
if($this->request->isPost()){
$data = $this->request->getPost();
$companyAddressForm->setData($data);
$clone->setData($data['address2']);
$isFormOneValid = $companyAddressForm->isValid();
//$isFormTwoValid = $clone->isValid();
}
$view = new ViewModel();
$view->companyAddressForm = $companyAddressForm;
$view->clone = $clone;
return $view;
}
This is working as I expected it to work, forms are rendering and validating correctly, I want to know whether it is a correct way or a hack?
If both of the forms are exactly the same then you don't need to declare and validate two forms in the controller action.
Reason:
If there are two forms rendered your HTML page. Only one of the forms can be posted by the users at a time and you need to validate only one form at a time. What you are doing now is to validate the same form with the same post data over again. So either $isFormOneValid, $isFormTwoValid are both true or both false.
Instead, declare only one form, render it twice in your view, and upon post, validate it with the post data. If the two forms differ in properties, filters, validators, etc. then you can create two methods like $form->applyForm1Validarots() and $form->applyForm2Validarots, check the value of your select element, and call the appropriate method to apply the validaorts / filters before calling isValid() on it.
Hope I helped