Zend Framework

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 07-03-2017 10:50:17

RomainG
Membre
Date d'inscription: 10-06-2015
Messages: 53

Traduction aléatoire des erreurs formulaire

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 :

Code:

$translator = $e->getApplication()->getServiceManager()->get('MvcTranslator');
AbstractValidator::setDefaultTranslator($translator);

Sans succès...

Une idée ?

Romain

Hors ligne

 

#2 07-03-2017 12:02:52

JGreco
Modérateur
Date d'inscription: 22-12-2012
Messages: 400

Re: Traduction aléatoire des erreurs formulaire

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à.


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#3 07-03-2017 13:21:56

RomainG
Membre
Date d'inscription: 10-06-2015
Messages: 53

Re: Traduction aléatoire des erreurs formulaire

Bonjour JGreco,

voici en partie, ma class Form :

Code:

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

Code:

$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

 

#4 08-03-2017 09:28:00

JGreco
Modérateur
Date d'inscription: 22-12-2012
Messages: 400

Re: Traduction aléatoire des erreurs formulaire

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.


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#5 08-03-2017 12:06:25

RomainG
Membre
Date d'inscription: 10-06-2015
Messages: 53

Re: Traduction aléatoire des erreurs formulaire

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

 

#6 08-03-2017 14:24:42

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1248

Re: Traduction aléatoire des erreurs formulaire

Tu as fait quoi ? Montres ton code


ZendFramework 2 Certified Architect

Hors ligne

 

#7 08-03-2017 14:27:03

JGreco
Modérateur
Date d'inscription: 22-12-2012
Messages: 400

Re: Traduction aléatoire des erreurs formulaire

Montre moi ce que tu as testé.

Moi je te demande d'inscrire un truc dans ce genre :

Code:

[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é.


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#8 08-03-2017 15:02:29

RomainG
Membre
Date d'inscription: 10-06-2015
Messages: 53

Re: Traduction aléatoire des erreurs formulaire

JGreco, c'est exactement ce que j'ai fait :

Code:

[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

 

#9 09-03-2017 09:46:33

JGreco
Modérateur
Date d'inscription: 22-12-2012
Messages: 400

Re: Traduction aléatoire des erreurs formulaire

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.


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#10 09-03-2017 11:14:10

RomainG
Membre
Date d'inscription: 10-06-2015
Messages: 53

Re: Traduction aléatoire des erreurs formulaire

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

 

#11 09-03-2017 11:29:08

JGreco
Modérateur
Date d'inscription: 22-12-2012
Messages: 400

Re: Traduction aléatoire des erreurs formulaire

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

http://img4.hostingpics.net/thumbs/mini_29421609032017113352.png


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#12 09-03-2017 15:37:21

RomainG
Membre
Date d'inscription: 10-06-2015
Messages: 53

Re: Traduction aléatoire des erreurs formulaire

Je me doutais bien que ce n'était pas lié à la nature du champ mais à force...
Voici le code du formulaire :

Code:

[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 :

Code:

[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

 

#13 09-03-2017 15:52:24

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1248

Re: Traduction aléatoire des erreurs formulaire

Hello, bon déjà désolé mais ton code est immonde hmm.

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.


ZendFramework 2 Certified Architect

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages