Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Bonjour à tous,
je rencontre un problème assez particulier que je n'arrive pas à résoudre au niveau de la validation de mes formulaires.
Voici le topo :
j'ai un formulaire avec un champ de type text (requit) et un champ de type select (multiple et requit).
Quand je soumets le formulaire avec les champs vides, le message d'erreur du champ text est bien traduit en français mais celui du champ select n'est pas traduit (Value is required and can't be empty).
Je précise quand même que ce texte de validation (Value is required and can't be empty) est traduit en français dans mon fichier de traduction.
Ce que j'ai également fait, c'est de rajouter ceci dans le Module.php de mon application :
$translator = $e->getApplication()->getServiceManager()->get('MvcTranslator'); AbstractValidator::setDefaultTranslator($translator);
Sans succès...
Une idée ?
Romain
Hors ligne
Bonjour,
j'aimerai voir dans ton service comment tu valide ton champ select (instanciation des validator sur le champ select). Car je suppose fortement que le problème vienne de là.
Hors ligne
Bonjour JGreco,
voici en partie, ma class Form :
class MyForm extends Form implements InputFilterProviderInterface { public function init() { $select = new Select('field'); $this->add($select); } public function getInputFilterSpecification() { return [ 'field' => [ 'required' => true ] ]; } }
Et dans mon controller je fais un simple
$form->setData($request->getPost()); if ($form->isValid() { // récupération des données et envoie de celles ci dans mon service pour sauvegarde }
Hors ligne
Bonjour,
Le problème viens de ton new Select. Il ne faut pas faire cela car tu bypass l'initializer de l'abstract validator sur le fameux setTranslator.
L'initializer ne fonctionne que quand tu utilises le service manager. Or un new directement ne marchera jamais quand bien même ton module.php ferait l'instantiation de ton setTranslator (il n'est pas static donc ton new Select ignore complètement cela)
Donc pour résumer :
- Enlève ton initialisation du translator dans ton module.php cela ne sert a rien.
- Utilise dans ta classe form la méthode add pour ajouter ton select.
Et cela devrait régler ton soucis.
Hors ligne
Salut JGreco,
Je viens de tester ta solution et ça ne fonctionne pas du tout. Le message d'erreur du Select est toujours en anglais et les autres sont bien en français...
Je vais essayer de creuser plus en détails.
Hors ligne
Tu as fait quoi ? Montres ton code
Hors ligne
Montre moi ce que tu as testé.
Moi je te demande d'inscrire un truc dans ce genre :
[lang=php] $this->add([ 'name' => 'testField', 'type' => 'Zend\Form\Element\Select', 'options' => [ 'label' => 'field_label', 'value_options' => [ 'test' => 'test_label', 'other_value' => 'other_value_label' ], ], 'empty_option' => 'label_empty', ]);
Car il n'y as que dans ce cas là, ou le type que tu saisis est instancié par le service manager, et donc l'initialiser est également appelé.
Hors ligne
JGreco, c'est exactement ce que j'ai fait :
[lang=php] // la fonction est appelée dans le constructeur de la classe public function addElements() { $name = new Text('name'); $name->setOptions(array('label' => 'name', 'column-size' => 'lg-10'))->setAttributes(array('id' => 'name'))->setLabelAttributes(array('class' => 'col-lg-2 required')); $providerModel = $this->serviceManager->get('Provider'); $tab = $providerModel->getSelectElementData(array(3,5)); $this->add([ 'name' => 'providers', 'type' => 'select', 'options' => [ 'label' => 'providers', 'label_attributes' => [ 'class' => 'col-lg-2 required' ], 'column-size' => 'lg-10', 'value_options' => $tab ], 'attributes' => [ 'multiple' => 'multiple', 'id' => 'providers', 'class' => 'form-control', 'size' => count($tab), 'data-filter' => 1, 'data-position' => 'top', 'lang' => substr($this->serviceManager->get('MvcTranslator')->getLocale(), 0, 2) ] ], ['priority' => 10]); $this->add($name, array('priority' => 55)) }
J'ai également supprimé l'AbstractValidator du Module.php.
Hors ligne
Bonjour,
Comme dit ici : https://framework.zend.com/manual/2.1/e … forms.html
And now comes the first catch.
If you are creating your form class by extending Zend\Form\Form, you must not add the custom element in the __construct-or (as we have done in the previous example where we used the custom element’s FCQN), but rather in the init() method:
Ton constructeur ne doit pas appeler une méthode qui initialise tes champs de formulaires, utilises la méthode init pour cela.
Je te conseille par ailleurs de lire cette page dans son ensemble, tu en apprendras plus sur ce composant formulaire.
Hors ligne
Bonjour,
j'ai effectué les changements comme tu l'as indiqué mais sans succès...
Est-ce que ça pourrait être lié au fait qu'il s'agit d'un select multiple ?
J'ai d'autres formulaires avec des select simple et le message d'erreur est bien traduit...
Hors ligne
Si possible pourrait tu me coller toute ta classe form, avec juste des bout de code c'est dur de voir ce qui vas pas. (Avec également la partie des input filter specification etc)
Et la vue qui affiche le form également
Edit: Et pour répondre à ta question, non j'ai des select multiples qui marchent très bien avec ce que je te dis donc la nature du champ ne le rend pas moins traduisible sur ses message d'erreurs
Hors ligne
Je me doutais bien que ce n'était pas lié à la nature du champ mais à force...
Voici le code du formulaire :
[lang=php] <?php namespace Service\Form; use Zend\Form\Form; use Service\Entity\Service; use Zend\Form\Element\Text; use Zend\Form\Element\Hidden; use Zend\Form\Element\Select; use Zend\Form\Element\Textarea; use Zend\Form\Element\Button; use Application\Mapper\LanguageMapperInterface; use Zend\InputFilter\InputFilterProviderInterface; use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator; class ServiceForm extends Form implements InputFilterProviderInterface { protected $language; protected $serviceManager; public function __construct(LanguageMapperInterface $languageService, $serviceManager){ parent::__construct('service'); $this->language = $languageService; $this->serviceManager = $serviceManager; $this->setAttribute('method', 'post'); } public function init() { $this->setHydrator(new DoctrineHydrator ( $this->serviceManager->get('entityManager') )); $this->setObject(new Service()); $this->addElements(); } public function addElements() { $basePath = $this->serviceManager->get('viewhelpermanager')->get('basepath'); $headScript = $this->serviceManager->get('viewhelpermanager')->get('headscript'); $headScript->appendFile($basePath('/../js/autonumeric.js')); $id = new Hidden('idservice'); $id->setAttribute('id', 'idservice'); $date = new Hidden('date'); $date->setAttribute('id', 'date'); $name = new Text('name'); $name->setOptions(array('label' => 'name', 'column-size' => 'lg-10'))->setAttributes(array('id' => 'name'))->setLabelAttributes(array('class' => 'col-lg-2 required')); $description = new Textarea('description'); $description->setOptions(array('label' => 'description', 'column-size' => 'lg-10'))->setAttributes(array('rows' => 10, 'id' => 'description', 'class' => 'ckeditor'))->setLabelAttributes(array('class' => 'col-lg-2')); if(count($this->language->getLanguages())>1){ $inputGroupBtnLang = $this->serviceManager->get('ViewHelperManager')->get('inputGroupBtnLang'); $name->setOption('add-on-append', $inputGroupBtnLang('service')); $description->setAttributes(['class' => 'ckeditor multilang']); foreach ($this->language->getLanguages() as $idlanguage => $label) { $this->add([ 'name' => 'name_'.$idlanguage, 'type' => 'hidden', 'attributes' => [ 'id' => 'name_'.$idlanguage ] ]); $this->add([ 'name' => 'description_'.$idlanguage, 'type' => 'hidden', 'attributes' => [ 'id' => 'description_'.$idlanguage ] ]); } } $current_language = new Hidden('current_language'); $current_language->setAttributes(array('value' => substr($this->serviceManager->get('MvcTranslator')->getLocale(), 0, 2), 'id' => 'current_language')); $this->add($current_language, array('priority' => 40)); $price = new Text('price'); $price->setOptions(array('label' => 'normal rate adult', 'add-on-prepend' => '<i class="fa fa-euro fa-fw"></i>', 'column-size' => 'lg-10'))->setAttributes(array('class' => 'autonumeric small', 'id' => 'price', 'data-a-dec'=>',', 'data-a-sep'=>' ', 'data-v-min'=>0, 'required' => 'required'))->setLabelAttributes(['class' => 'col-lg-2 required']); $discount = new Text('discount'); $discount->setOptions(array('label' => 'discount', 'add-on-prepend' => '<i class="fa fa-euro fa-fw"></i>', 'column-size' => 'lg-10'))->setAttributes(array('id' => 'discount', 'class' => 'autonumeric small', 'data-a-dec'=>',', 'data-a-sep'=>' ', 'data-v-min'=>0))->setLabelAttributes(['class' => 'col-lg-2']); $price_child = new Text('price_child'); $price_child->setOptions(array('label' => 'normal rate child', 'add-on-prepend' => '<i class="fa fa-euro fa-fw"></i>', 'column-size' => 'lg-10'))->setAttributes(array('class' => 'autonumeric small', 'id' => 'price_child', 'data-a-dec'=>',', 'data-a-sep'=>' ', 'data-v-min'=>0))->setLabelAttributes(['class' => 'col-lg-2']); $discount_child = new Text('discount_child'); $discount_child->setOptions(array('label' => 'discount', 'add-on-prepend' => '<i class="fa fa-euro fa-fw"></i>', 'column-size' => 'lg-10'))->setAttributes(array('class' => 'autonumeric small', 'id' => 'discount_child', 'data-a-dec'=>',', 'data-a-sep'=>' ', 'data-v-min'=>0))->setLabelAttributes(['class' => 'col-lg-2']); $categoryModel = $this->serviceManager->get('Category'); $elements = $categoryModel->getSelectElementData(); $idcategory = new Select('idcategory'); $idcategory->setOptions(array('label' => 'category', 'column-size' => 'lg-10'))->setAttributes(array('id' => 'idcategory'))->setLabelAttributes(array('class' => 'col-lg-2'))->setValueOptions($elements)->setEmptyOption('category'); $providerModel = $this->serviceManager->get('Provider'); $tab = $providerModel->getSelectElementData(array(3,5)); $this->add([ 'name' => 'providers', 'type' => 'select', 'options' => [ 'label' => 'providers', 'label_attributes' => [ 'class' => 'col-lg-2 required' ], 'column-size' => 'lg-10', 'value_options' => $tab, ], 'attributes' => [ 'multiple' => 'multiple', 'id' => 'providers', 'class' => 'form-control', 'size' => count($tab), 'data-filter' => 1, 'data-position' => 'top', 'lang' => substr($this->serviceManager->get('MvcTranslator')->getLocale(), 0, 2) ] ], ['priority' => 10]); // $providers = new Select('providers'); // $providers->setOptions(array('label' => 'providers', 'column-size' => 'lg-10'))->setLabelAttributes(array('class' => 'col-lg-2 required'))->setAttributes(array('multiple' => true, 'id' => 'providers', 'class' => 'form-control')); // $providers->setAttributes(['size' => count($tab), 'data-filter'=>1, 'data-position'=>'top', 'lang' => substr($this->serviceManager->get('MvcTranslator')->getLocale(), 0, 2)])->setValueOptions($tab); $type = new Select('type'); $type->setOptions(['label' => 'type', 'column-size' => 'lg-10'])->setAttributes(['class' => 'small form-control'])->setValueOptions(\Service\Model\Service::getInstance()->getTypes())->setLabelAttributes(['class' => 'col-lg-2 required']); $externalRef = new Text('external_ref'); $externalRef->setOptions(['label' => 'external_ref', 'column-size' => 'lg-10'])->setAttributes(['class' => 'form-control'])->setLabelAttributes(['class' => 'col-lg-2']); $button = new Button('submit'); $button->setOptions(array('label' => 'Save', 'column-size' => 'lg-10 col-lg-offset-2', 'fontAwesome' => 'check'))->setAttributes(array('id' => 'submitbutton', 'class' => 'btn-primary', 'type' => 'submit', 'value' => 'save')); $this->add($id, array('priority' => 60)) ->add($date, ['priority' => 57]) ->add($name, array('priority' => 55)) ->add($idcategory, array('priority' => 50)) ->add($description, array('priority' => 45)) ->add($price, array('priority' => 30)) ->add($discount, array('priority' => 25)) ->add($price_child, array('priority' => 20)) ->add($discount_child, array('priority' => 15)) // ->add($providers, array('priority' => 10)) ->add($type, ['priority' => 5]) ->add($externalRef, ['priority' => 2]) ->add($button, array('priority' => 1)); } /* (non-PHPdoc) * @see \Zend\InputFilter\InputFilterProviderInterface::getInputFilterSpecification() */ public function getInputFilterSpecification() { return [ 'idservice' => [ 'required' => false, 'filters' => [ ['name' => 'Int'] ] ], 'date' => [ 'required' => false ], 'name' => [ 'required' => true, 'filters' => [ ['name' => 'StringTrim'], ['name' => 'StripTags'] ], 'validators' => [ ['name' => 'notEmpty'] ] ], 'description' => [ 'required' => false, 'filters' => [ ['name' => 'StringTrim'] ] ], 'idcategory' => [ 'required' => false ], 'price' => [ 'required' => true, 'filters' => [ ['name' => 'StripTags'], ['name' => 'StringTrim'] ], ], 'discount' => [ 'required' => false, 'filters' => [ ['name' => 'StripTags'], ['name' => 'StringTrim'] ] ], 'price_child' => [ 'required' => false, 'filters' => [ ['name' => 'StripTags'], ['name' => 'StringTrim'] ] ], 'discount_child' => [ 'required' => false, 'filters' => [ ['name' => 'StripTags'], ['name' => 'StringTrim'] ] ], 'providers' => [ 'required' => true, ], 'type' => [ 'required' => true ] ]; } }
Et le code de la vue qui affiche le formulaire :
[lang=php] <?php $this->headMeta()->appendHttpEquiv('pragma', 'no-cache'); $this->headScript()->appendFile($this->basePath() . '/../js/ckeditor/ckeditor.js'); $this->headScript()->appendFile($this->basePath() . '/../js/ckeditor/adapters/jquery.js'); $this->headScript()->appendFile($this->basePath() . '/../js/ckfinder/ckfinder.js'); echo "<script>CKFinderBasePath = '" . $this->basePath() . "/../js/ckfinder/';</script>"; ?> <a class="backlink text-muted" href="<?php if($this->form->get('redirect') && $this->form->get('redirect')->getValue()){echo $this->form->get('redirect')->getValue();}else{echo $_SERVER['HTTP_REFERER'];} ?>"><i class="fa fa-chevron-left"></i> <?php echo $this->translate('back'); ?></a> <h1><?php echo $this->translate('New Service'); ?></h1> <div class="well"> <?php $form = $this->form; $form->setAttribute('action', $this->url('application/default', array('controller' => 'service', 'action' => 'add'), true))->prepare(); $form->get('description')->setAttribute('data-url', $this->basePath('/service/gettranslation')); echo $this->form($form,\TwbBundle\Form\View\Helper\TwbBundleForm::LAYOUT_HORIZONTAL); ?> </div> <script> $(document).ready(function() { var $btnInput = $('div.input-lang').clone(true); $('#name').siblings('span.input-group-addon').remove(); $('#name').after($btnInput); $("form#service #submit").click(function(){ $('form#service #providers').closest('.form-group').removeClass('has-error'); if(!$("form#service #providers").val()){ $('form#service #providers').closest('.form-group').addClass('has-error'); $("form#service #providers").closest('div').find('button.ms-choice').trigger(('click')); return false; } }); }); </script>
Hors ligne
Hello, bon déjà désolé mais ton code est immonde .
Premièrement on injecte JAMAIS le service manager / container / service locator dans une classe. JAMAIS JAMAIS JAMAIS ! Donc pour avoir accès à l'entity manager tu l'injectes directement. Evidement toutes les dépendances que tu récupères dynamiquement via le service manager tu dois les passer à ton constructeur (le ViewHelperManager étant un service manager spécialisé, il ne s'injecte pas non plus). D'ailleurs je ne vois pas ce que vient faire le ViewHelperManager dans ta classe Form, ça n'a rien à y faire. Tu veux ajouter du JS tu le fais dans ta vue, une aide de vue si tu veux mais pas dans le formulaire. JAMAIS JAMAIS JAMAIS !
Ensuite on t'a dit de ne pas utiliser de new pour créer tes éléments de formulaire, donc quand tu dis que tu l'as fait, je dis non. Suffit de lire la 4ème ligne de ta méthode AddElements.
Enfin pour ton multi select tu n'as pas besoin de passer le translator, normalement il fait les traductions tout seul automatiquement.
Bref fais un peu de clean déjà ça te permettra d'y voir beaucoup plus clair dans ton formulaire. Tes éléments Select tu peux les remplir de manière automatique en utilisant Doctrine, donc ne t'en prives pas. DoctrineModule ou DoctrineORMModule je ne sais plus lequel, apporte de nouveaux éléments de formulaire qui gèrent tout pour toi. Ca te simplifiera grandement la vie et ça t'éviteras d'avoir autant de bazar dans ton formulaire.
Hors ligne