2017-09-06 3 views
0

Salut J'ai une entité qui containt (OneToMany) Documentation. Dans Documentation j'ai un fichier, j'utilise vichuploader pour le télécharger mais j'ai un problème, quand enregistrer mon formulaire j'ai une erreur qui me dit que le nom du fichier est nul (erreur de doctrine). Est-il possible d'intégrer un champ vichuploader sur la collection de formulaires? Si quelqu'un a une idée :) j'ai poster mes fichiers Thank youSymfony vichuploader dans la collection de formulaires

product.php

class Product 
{ 
/** 
* @var int 
* 
* @ORM\Column(name="id", type="integer") 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="AUTO") 
*/ 
private $id; 

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

/** 
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Documentation", mappedBy="product", cascade={"persist", "remove"}) 
* @ORM\JoinColumn(nullable=true) 
* @Assert\Valid() 
*/ 
private $documentations; 

/** 
* Constructor 
*/ 
public function __construct() 
{ 
    $this->documentations = new \Doctrine\Common\Collections\ArrayCollection(); 
} 

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

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

    return $this; 
} 

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

/** 
* Add documentation 
* 
* @param \AppBundle\Entity\Documentation $documentation 
* 
* @return Product 
*/ 
public function addDocumentation(\AppBundle\Entity\Documentation $documentation) 
{ 
    $documentation->setProduct($this); 
    $this->documentations[] = $documentation; 

    return $this; 
} 

/** 
* Remove documentation 
* 
* @param \AppBundle\Entity\Documentation $documentation 
*/ 
public function removeDocumentation(\AppBundle\Entity\Documentation $documentation) 
{ 
    $this->documentations->removeElement($documentation); 
} 

/** 
* Get documentations 
* 
* @return \Doctrine\Common\Collections\Collection 
*/ 
public function getDocumentations() 
{ 
    return $this->documentations; 
} 
} 

Documentation.php

class Documentation 
{ 
/** 
* @var int 
* 
* @ORM\Column(name="id", type="integer") 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="AUTO") 
*/ 
private $id; 

/** 
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Product", inversedBy="documentations") 
*/ 
private $product; 

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

/** 
* @Vich\UploadableField(mapping="product_documentations", fileNameProperty="fileName") 
* @Assert\NotBlank(message="Vous devez joindre un fichier", groups={"add"}) 
* @Assert\File(
*  maxSize = "20M", 
*  maxSizeMessage = "Le fichier est trop gros, il doit faire {{ limit }} {{ suffix }}" 
*) 
*/ 
private $file; 

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

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


/** 
* Get id 
* 
* @return int 
*/ 
public function getId() 
{ 
    return $this->id; 
} 
/** 
* Constructor 
*/ 
public function __construct() 
{ 
    $this->groups = new \Doctrine\Common\Collections\ArrayCollection(); 
} 

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

    return $this; 
} 

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

/** 
* @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $file 
* 
* @return Documentation 
*/ 
public function setFile(File $file = null) 
{ 
    $this->file = $file; 
    if ($file) { 
     $this->updatedAt = new \DateTimeImmutable(); 
    } 
    return $this; 
} 

/** 
* @return File|null 
*/ 
public function getFile() 
{ 
    return $this->file; 
} 

/** 
* @param string $fileName 
* 
* @return Documentation 
*/ 
public function setFileName($fileName) 
{ 
    $this->fileName = $fileName; 

    return $this; 
} 

/** 
* @return string|null 
*/ 
public function getFileName() 
{ 
    return $this->fileName; 
} 

/** 
* Set updatedAt 
* 
* @param \DateTime $updatedAt 
* 
* @return Documentation 
*/ 
public function setUpdatedAt($updatedAt) 
{ 
    $this->updatedAt = $updatedAt; 

    return $this; 
} 

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

/** 
* Set product 
* 
* @param \AppBundle\Entity\Product $product 
* 
* @return Documentation 
*/ 
public function setProduct(Product $product = null) 
{ 
    $this->product = $product; 

    return $this; 
} 

/** 
* Get product 
* 
* @return \AppBundle\Entity\Product 
*/ 
public function getProduct() 
{ 
    return $this->product; 
} 
} 

DocumentationType.php

class DocumentationType extends AbstractType 
{ 

/** 
* @param FormBuilderInterface $builder 
* @param array    $options 
*/ 
public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->add(
      'name', 
      TextType::class, 
      array(
       'attr' => array(
        'placeholder' => 'Nom' 
       ), 
       'label' => 'Nom :' 
      ) 
     ) 
     ->add(
      'file', 
      FileType::class, 
      array(
       'attr' => array(
        'placeholder' => 'Fichier' 
       ), 
       'required' => false, 
       'label'  => 'Fichier :' 
      ) 
     ) 
    ; 
} 

/** 
* @param OptionsResolver $resolver 
*/ 
public function configureOptions(OptionsResolver $resolver) 
{ 
    $resolver->setDefaults(array(
     'data_class' => Documentation::class, 
     'attr' => array(
      'novalidate' => 'novalidate' 
     ) 
    )); 
} 
} 

ProductType.php

class ProductType extends AbstractType 
{ 
/** 
* {@inheritdoc} 
*/ 
public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->add('name') 
     ->add(
      'documentations', 
      CollectionType::class, 
      array(
       'entry_type' => DocumentationType::class, 
       'by_reference' => false, 
       'allow_add' => true, 
       'allow_delete' => true, 
       'label' => 'Fichier(s) :', 
       'prototype' => true 
      ) 
     ) 
    ; 
} 

/** 
* {@inheritdoc} 
*/ 
public function configureOptions(OptionsResolver $resolver) 
{ 
    $resolver->setDefaults(array(
     'data_class' => 'AppBundle\Entity\Product' 
    )); 
} 

/** 
* {@inheritdoc} 
*/ 
public function getBlockPrefix() 
{ 
    return 'appbundle_product'; 
} 
} 

new.html.twig

{% extends 'base.html.twig' %} 

{% block body %} 
<h1>Product creation</h1> 

{{ form_start(form) }} 
    {{ form_row(form.name) }} 
    <a href="#" id="add_documentation" data-prototype-add="div#appbundle_product_documentations" class="btn btn-default btn-collection-add"> 
     <span class="glyphicon glyphicon-plus"></span> Ajouter une documentation 
    </a> 
    {{ form_row(form.documentations) }} 
    <input type="submit" value="Create" /> 
{{ form_end(form) }} 

<ul> 
    <li> 
     <a href="{{ path('product_index') }}">Back to the list</a> 
    </li> 
</ul> 

<script> 
    // On ajoute un nouveau champ à chaque clic sur le lien d'ajout. 
    $('.btn-collection-add').click(function (e) { 
     addDocumentation($($(this).data('prototype-add'))); 
     e.preventDefault(); // évite qu'un # apparaisse dans l'URL 
     return false; 
    }); 

    // La fonction qui ajoute un formulaire CategoryType 
    function addDocumentation($container) { 
     var index = $container.find(':input').length; 
     // Dans le contenu de l'attribut « data-prototype », on remplace : 
     // - le texte "__name__" qu'il contient par le numéro du champ 
     var template = $container.attr('data-prototype').replace(/__name__/g, index); 
     // On crée un objet jquery qui contient ce template 
     var $prototype = $(template); 
     // On ajoute le prototype modifié à la fin de la balise <div> 
     $container.append($prototype); 
     // Enfin, on incrémente le compteur pour que le prochain ajout se fasse avec un autre numéro 
     index++; 
    } 

    // Ajout du listener sur le clic du lien pour effectivement supprimer l'entrée de la collection. 
    $(document).on('click', '.btn-collection-delete', function (e) { 
     $(this).closest('.panel').remove(); 
     e.preventDefault(); // évite qu'un # apparaisse dans l'URL 
     return false; 
    }); 
</script> 

{% endblock %} 

NewAction sur le contrôleur

public function newAction(Request $request) 
{ 
    $product = new Product(); 
    $form = $this->createForm(
     'AppBundle\Form\ProductType', 
     $product, 
     array(
      'validation_groups' => array('add') 
     ) 
    ); 
    $form->handleRequest($request); 

    if ($form->isSubmitted() && $form->isValid()) { 
     $em = $this->getDoctrine()->getManager(); 
     $em->persist($product); 
     $em->flush(); 

     return $this->redirectToRoute('product_show', array('id' => $product->getId())); 
    } 

    return $this->render('product/new.html.twig', array(
     'product' => $product, 
     'form' => $form->createView(), 
    )); 
} 

section Mon vich_uploader sur config.yml

vich_uploader: 
db_driver: orm 
mappings: 
    product_documentations: 
     uri_prefix:   /products/documentations 
     upload_destination: '%kernel.root_dir%/../web/products/documentations' 
     inject_on_load:  false 
     delete_on_update: true 
     delete_on_remove: true 
+0

Vous voulez donc télécharger le fichier et si l'utilisateur ne télécharge pas le fichier et ne soumet pas le formulaire que vous voulez afficher? Ai-je raison? – KondukterCRO

+0

Salut, non, j'ai mon formulaire de produit qui intègre plusieurs formulaires de documentation. Je souhaite ajouter plusieurs formulaires de documentation avec le téléchargement. Mais quand je crée un produit avec le fichier de documentation et la forme valide j'ai une erreur: Une exception s'est produite pendant l'exécution de la documentation INSERT INTO (nom, nom_fichier, update_at, product_id) VALUES (?,?,?,?) 'Avec params [" tt ", null," 2017-09-07 09:22:05 ", 5]: SQLSTATE [23000]: Violation de la contrainte d'intégrité: 1048 La colonne 'nom_fichier' ne peut pas être nulle – eldiablo62

+0

Je pense que le produit persiste vichuploader n'a pas fait le travail (ne pas télécharger, ne pas mettre le nom dans le nom de fichier) – eldiablo62

Répondre

0

J'ai trouvé la solution je lost * @Vich \ Uploadable dans ma documentation en Description de l'action