Comportement différent selon l'environnement

Champ requis en prod, alors que pas en dev'

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour à tous !

J'ai un comportement que je n'arrive pas à cerner, et qui me paraît presque être un vrai bug de Symfony que de l'ICC.

J'ai un formulaire avec un champ de type choice, dont je rends chaque option séparément en utilisant form_widget(form.choiceField.0), form_widget(form.choiceField.1), etc.
Entre les options ainsi rendues, j'ai d'autres champs qui viennent. Le code est ci-dessous. L'idée étant de choisir un type de média et de renseigner le ou les champ(s) relatifs à ce type.

Maintenant, il se trouve que si les options de mon choiceField sont forcément requises, il n'en est pas de même pour les champs "intercalaires". Avec l'environnement de dev, pas de problème. Mais avec l'environnement de production, ces champs intercalaires, même s'ils sont bien spécifiés comme non requis dans le FormType, l'attribut required est ajouté. Du coup, on doit renseigner les informations pour tous les types de média alors qu'on n'enregistrera que les données d'un seul.

Il paraît que c'est quelque chose de connu, mais je n'ai pas réussi à en trouver trace sur le repository officiel, et n'ai pas de solution pour l'instant.
Est-ce que quelqu'un aurait déjà observé un tel comportement et aurait un workaround à me proposer ?

Je précise que je parle des environnements Symfony. Ce souci a été constaté sur trois machines différentes en comparant le code HTML généré en passant par app.php et app_dev.php sur la même machine, tous caches purgés.

Merci d'avance

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
<?php

namespace MyWonderfulBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;

/**
 * Media
 * @ORM\HasLifecycleCallbacks
 * @ORM\Table(name="media")
 * @ORM\Entity
 */
class Media
{
    const UPLOAD_DIR = 'uploads/medias';

    const VIDEO = 'video';
    const IMAGE = 'image';

    const YOUTUBE_EMBED_BASE = '//www.youtube.com/embed/';
    const VIMEO_EMBED_BASE = '//player.vimeo.com/video/';

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="type", type="string", length=255, nullable=false)
     */
    private $type;

    /**
     * The name of the media.
     * It can be the name of the image or the identifier of the video
     *
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=true)
     */
    private $name;

    /**
     * The path of the media.
     * This can be the base URL for a distant media, mostly the base embed URL
     * for videos
     *
     * @var string
     *
     * @ORM\Column(name="path", type="string", length=255, nullable=true)
     */
    private $path;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="updatedAt", type="datetime", nullable=true)
     */
    private $updatedAt;

    public function __toString() {
        return $this->getName();
    }

    public static function getTypeMedia() {
        return array(self::IMAGE => self::IMAGE, self::VIDEO => self::VIDEO);
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set type
     *
     * @param string $type
     * @return Media
     */
    public function setType($type)
    {
        $this->type = $type;

        return $this;
    }

    /**
     * Get type
     *
     * @return string
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * Set path
     *
     * @param string $path
     * @return Media
     */
    public function setPath($path)
    {
        $this->path = $path;

        return $this;
    }

    /**
     * Get path
     *
     * @return string
     */
    public function getPath()
    {
        return $this->path;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Media
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set updatedAt
     *
     * @param string $updatedAt
     * @return Media
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    /**
     * Get updatedAt
     *
     * @return string
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }

    /*************************************************************/

     /**
     * @Assert\Image(
     *     minWidth = 600,
     *     minWidthMessage="L'image doit avoir une largeur minimale de 660 pixels",
     *     minHeight = 400,
     *     minHeightMessage="L'image doit avoir une hauteur minimale de 412 pixels",
     * )
     */
    public $file;

    // Getters et setters comme à l'accoutumée
}

Mon entité Media

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<?php

namespace MyWonderfulBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

use MyWonderfulBundle\Entity\Media;

class MediaType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('type', 'choice', array(
                'choices'  => Media::getTypeMedia(),
                'expanded' => true,
                'multiple' => false,
                'attr'     => array(
                    'class' => 'radio'
                )
            ))
            ->add('video_url', 'text', array(
                'required' => false,
            ))
            ->add('file', 'file', array(
                'required' => false,
                'label'    => 'Image',
                'attr'     => array(
                    'accept' => 'image/*',
                    'class'  => 'filestyle'
                )
            ))
            ->add('name', 'hidden')
            ->add('path', 'hidden')
            ->add('updatedAt', 'datetime', array(
                'data'  => new \DateTime(),
                'attr'  => array('class' => 'hidden'),
                'label' => false
            ))
        ;
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'MyWonderfulBundle\Entity\Media'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'my_wonderful_bundle_media';
    }
}

Le FormType associé

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<div class="well">

  {% if form.vars.value is not empty -%}

      {% if form.type.vars.value == constant('MyWonderfulBundle\\Entity\\Media::IMAGE') -%}
          {{ form.vars.value|media({'class':'img-thumbnail ' ~ form.parent.vars.name|slice(0, -1)}) }}
      {% elseif form.type.vars.value == constant('MyWonderfulBundle\\Entity\\Media::VIDEO') -%}
          {{ form.vars.value|media({'width':'150','height':'150'}) }}
      {%- endif %}
  {%- endif %}

  <div class="form-group clearfix">
    {{ form_widget(form.type.0, (displayVideo ? {} : {'attr': {'checked': true}, 'label_attr': {'class': 'hidden'}})) }}
  </div>
  <div class="form-group clearfix">
      {{ form_widget(form.file) }}
  </div>
  {% if displayVideo %}
  <div class="form-group clearfix">
      {{ form_widget(form.type.1) }}
  </div>
  <div class="form-group clearfix">
    {{ form_widget(form.video_url) }}
  </div>
  {% endif %}
  {{ form_widget(form.name) }}
  {{ form_widget(form.updatedAt) }}
</div>

Le template pour le formulaire de l'entité

Edit 9 octobre 2015

Il n'est pas impossible que ce soit dû à l'utilisation d'une macro plutôt que le système de templating. La piste me vient de cette discussion, plus précisement la réponse de stof qui précise un souci avec la gestion de required du fait des macros existantes.

Edit 9 octobre 2015 2

Fausse joie : avec le templating, c'est pareil… Voici le HTML généré par la même machine et le même code, en haut en dev' et en bas en prod' :

1
2
3
<input id="my_wonderfulbundle_product_galleryMedias_1_file" name="my_wonderfulbundle_product[galleryMedias][1][file]" accept="image/*" class="filestyle ajaxUpload" data-uri="/app_dev.php/media/_upload" data-target="uploads/medias" type="file">

<input id="my_wonderfulbundle_product_galleryMedias_1_file" name="my_wonderfulbundle_product[galleryMedias][1][file]" required="required" class="ajaxUpload" data-uri="/app.php/media/_upload" data-target="uploads/medias" type="file">

Temporairement, j'ai rendu mon champ "à l'ancienne". Mais si quelqu'un avait un comportement similaire, qu'il comprenait la raison et qu'il avait la bonne solution au sens Symfony, je serais très intéressé.

Édité par Ymox

Evitez qu'on vous dise de les lire : FAQ PHP et Symfony 2Tutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte