2017-09-06 9 views
0

안녕하세요 저는 엔터티 제품을 보유하고 있습니다 (OneToMany). 설명서에는 파일이 있는데, vichuploader를 사용하여 다운로드 할 수 있지만 문제가 있습니다. 양식을 저장할 때 파일 이름이 null (교리 오류) 인 오류가 있습니다. 양식 수집에 vichuploader 필드를 포함시킬 수 있습니까? 누군가가 아이디어 : 내가 당신양식 모음의 Symfony vichuploader

에게 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

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(), 
    )); 
} 

내가 가지고있는 솔루션 을 발견

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

파일을 업로드하고 사용자가 파일을 업로드하지 않고 양식을 제출하려면 오류 메시지를 표시 하시겠습니까? 내가 맞습니까? – KondukterCRO

+0

안녕하세요, 아니요, 여러 문서 형식을 포함하는 제품 양식이 있습니다. 업로드 할 때 몇 가지 문서 양식을 추가하고 싶습니다. 하지만 설명서 파일 및 유효한 양식이있는 제품을 만들 때 오류가 발생했습니다 : params [ " tt ", null,"2017-09-07 09:22:05 ", SQLSTATE [23000] : 무결성 제약 조건 위반 : 1048 열 'file_name'은 null 일 수 없습니다. – eldiablo62

+0

제품 지속성에 대한 생각은 vichuploader가 수행하지 않은 것입니다. 작품 (업로드하지 파일 이름에 이름을 넣어) – eldiablo62

답변

0

config.yml에 내 vich_uploader 섹션 내 문서에서 잃어버린 * @ Vich \ Uploadable tity description