2013-08-24 3 views
1

У меня есть два EntitiesSymfony2 - Embeding файла форма

- Kitchen 
- KitchenSubImage 

Каждая кухня имеет основное изображение, но также имеет много вложенных изображений (KitchenSubImage).

Я реализовал как объекты, так и их типы. На данный момент у меня отображается форма и реализовано все с How to Handle File Uploads with Symfony2, чтобы обрабатывать загрузку файла.

Проблема, которую я имею, заключается в том, что я понятия не имею, как обрабатывать обе загрузки файлов сразу. Это осложняется тем фактом, что на кухне может быть много вспомогательных изображений.

У меня есть следующее сообщение об ошибке в верхней части формы, когда я отправить форму:

Это значение должно быть типа PWD \ WebsiteBundle \ Entity \ KitchenSubImage.

Контроллер

<?php 

namespace PWD\AdminBundle\Controller; 

use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 

use PWD\WebsiteBundle\Entity\Kitchen; 
use PWD\AdminBundle\Form\Type\KitchenType; 

use PWD\WebsiteBundle\Entity\KitchenSubImage; 
use PWD\AdminBundle\Form\Type\KitchenSubImageType; 

class KitchenController extends Controller 
{ 
    public function indexAction() 
    { 
     return 'index'; 
    } 

    public function addAction(Request $request) 
    { 
     $kitchen = new Kitchen(); 
     $image = new KitchenSubImage(); 
     $kitchen->addSubImage($image); 
     $form = $this->createForm(new KitchenType(), $kitchen); 

     $form->handleRequest($request); 

     if ($form->isValid()) { 
      $kitchen->upload(); 
      return $this->render('PWDWebsiteBundle:Pages:home.html.twig'); 
     } 

     return $this->render('PWDAdminBundle:Pages:form-test.html.twig', array(
      'form' => $form->createView(), 
     )); 
    } 
} 

кухни Сущность

<?php 

namespace PWD\WebsiteBundle\Entity; 

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

/** 
* @ORM\Entity 
* @ORM\Table(name="kitchen") 
*/ 
class Kitchen 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    /** 
    * @ORM\Column(type="string", length=100) 
    * @Assert\NotBlank() 
    */ 
    protected $name; 

    /** 
    * @ORM\Column(type="text") 
    * @Assert\NotBlank() 
    */ 
    protected $description; 

    /** 
    * @Assert\File(maxSize="6000000") 
    * @Assert\Image(
    *  minWidth = 800, 
    *  maxWidth = 800, 
    *  minHeight = 467, 
    *  maxHeight = 467 
    *) 
    */ 
    protected $mainImage; 

    /** 
    * @ORM\Column(type="string", length=255, nullable=true) 
    */ 
    protected $mainImagePath; 

    /** 
    * @Assert\Type(type="PWD\WebsiteBundle\Entity\KitchenSubImage") 
    * @ORM\OneToMany(targetEntity="KitchenSubImage", mappedBy="kitchen") 
    */ 
    protected $subImage; 

    public function __construct() 
    { 
     $this->subImage = new ArrayCollection(); 
    } 

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

    public function setName($name) 
    { 
     $this->name = $name; 
    } 

    public function getDescription() 
    { 
     return $this->description; 
    } 

    public function setDescription($description) 
    { 
     $this->description = $description; 
    } 

    public function getMainImage() 
    { 
     return $this->mainImage; 
    } 

    public function setMainImage(UploadedFile $mainImage = null) 
    { 
     $this->mainImage = $mainImage; 
    } 

    public function getSubImage() 
    { 
     return $this->subImage; 
    } 

    public function setSubImage(KitchenSubImage $subImage = null) 
    { 
     $this->subImage = $subImage; 
    } 

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

    /** 
    * Set mainImagePath 
    * 
    * @param string $mainImagePath 
    * @return Kitchen 
    */ 
    public function setMainImagePath($mainImagePath) 
    { 
     $this->mainImagePath = $mainImagePath; 

     return $this; 
    } 

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

    public function getAbsolutePath() 
    { 
     return null === $this->mainImagePath 
      ? null 
      : $this->getUploadRootDir().'/'.$this->mainImagePath; 
    } 

    public function getWebPath() 
    { 
     return null === $this->mainImagePath 
      ? null 
      : $this->getUploadDir().'/'.$this->mainImagePath; 
    } 

    public function getUploadRootDir() 
    { 
     return __DIR__.'/../../../../web/'.$this->getUploadDir(); 
    } 

    public function getUploadDir() 
    { 
     return 'uploads/our-work'; 
    } 

    public function upload() 
    { 
     if (null === $this->getMainImage()) { 
      return; 
     } 

     $this->getMainImage()->move(
      $this->getUploadRootDir(), 
      $this->getMainImage()->getClientOriginalName() 
     ); 

     $this->mainImagePath = $this->getMainImage()->getClientOriginalName(); 

     $this->mainImage = null; 
    } 

    /** 
    * Add subImage 
    * 
    * @param \PWD\WebsiteBundle\Entity\KitchenSubImage $subImage 
    * @return Kitchen 
    */ 
    public function addSubImage(\PWD\WebsiteBundle\Entity\KitchenSubImage $subImage) 
    { 
     $this->subImage[] = $subImage; 
     $subImage->setKitchen($this); # used for persisting 

     return $this; 
    } 

    /** 
    * Remove subImage 
    * 
    * @param \PWD\WebsiteBundle\Entity\KitchenSubImage $subImage 
    */ 
    public function removeSubImage(\PWD\WebsiteBundle\Entity\KitchenSubImage $subImage) 
    { 
     $this->subImage->removeElement($subImage); 
    } 
} 

KitchenSubImage Сущность

<?php 

namespace PWD\WebsiteBundle\Entity; 

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

/** 
* @ORM\Entity 
* @ORM\Table(name="kitchenImages") 
*/ 
class KitchenSubImage 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    /** 
    * @Assert\Image(
    *  minWidth = 800, 
    *  maxWidth = 800, 
    *  minHeight = 467, 
    *  maxHeight = 467 
    *) 
    */ 
    public $image; 

    /** 
    * @ORM\Column(type="string", length=255, nullable=true) 
    */ 
    public $imagePath; 

    /** 
    * @ORM\ManyToOne(targetEntity="Kitchen", inversedBy="subImage") 
    * @ORM\JoinColumn(name="kitchen_id", referencedColumnName="id") 
    **/ 
    protected $kitchen; 

    public function getImage() 
    { 
     return $this->image; 
    } 

    public function setImage(UploadedFile $image = null) 
    { 
     $this->image = $image; 
    } 

    public function getAbsolutePath() 
    { 
     return null === $this->imagePath 
      ? null 
      : $this->getUploadRootDir().'/'.$this->imagePath; 
    } 

    public function getWebPath() 
    { 
     return null === $this->imagePath 
      ? null 
      : $this->getUploadDir().'/'.$this->imagePath; 
    } 

    public function getUploadRootDir() 
    { 
     return __DIR__.'/../../../../web/'.$this->getUploadDir(); 
    } 

    public function getUploadDir() 
    { 
     return 'uploads/our-work'; 
    } 

    public function upload() 
    { 
     if (null === $this->getImage()) { 
      return; 
     } 

     $this->getImage()->move(
      $this->getUploadRootDir(), 
      $this->getImage()->getClientOriginalName() 
     ); 

     $this->mainImagePath = $this->getImage()->getClientOriginalName(); 

     $this->mainImage = null; 
    } 

    /** 
    * Set imagePath 
    * 
    * @param string $imagePath 
    * @return KitchenSubImage 
    */ 
    public function setImagePath($imagePath) 
    { 
     $this->imagePath = $imagePath; 

     return $this; 
    } 

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

    /** 
    * Set kitchen 
    * 
    * @param \PWD\WebsiteBundle\Entity\Kitchen $kitchen 
    * @return KitchenSubImage 
    */ 
    public function setKitchen(\PWD\WebsiteBundle\Entity\Kitchen $kitchen = null) 
    { 
     $this->kitchen = $kitchen; 

     return $this; 
    } 

    /** 
    * Get kitchen 
    * 
    * @return \PWD\WebsiteBundle\Entity\Kitchen 
    */ 
    public function getKitchen() 
    { 
     return $this->kitchen; 
    } 

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

KitchenType:

<?php 

namespace PWD\AdminBundle\Form\Type; 

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

class KitchenType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('name'); 
     $builder->add('description', 'textarea'); 
     $builder->add('mainImage', 'file'); 
     $builder->add('subImage', 'collection', array(
      'type' => new KitchenSubImageType(), 
      'label' => false, 
      'allow_add' => true, 
      'by_reference' => false, 
     )); 
     $builder->add('submit', 'submit'); 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'PWD\WebsiteBundle\Entity\Kitchen', 
      'cascade_validation' => true, 
     )); 
    } 

    public function getName() 
    { 
     return 'kitchen'; 
    } 
} 

KitchenSubImageType:

<?php 

namespace PWD\AdminBundle\Form\Type; 

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

class KitchenSubImageType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('image', 'file', array('label' => 'Sub Images')); 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'PWD\WebsiteBundle\Entity\KitchenSubImage', 
     )); 
    } 

    public function getName() 
    { 
     return 'kitchensubimage'; 
    } 
} 

ответ

1

Добро пожаловать. Вид желания, что вы приняли мое предыдущее предложение и ушли, хотя пример блога/тегов. У вас по-прежнему возникают проблемы с картинками с коллекциями.

В вашей кухне сущности, все это не так:

protected $subImage; 

public function getSubImage() 
{ 
    return $this->subImage; 
} 
public function setSubImage(KitchenSubImage $subImage = null) 
{ 
    $this->subImage = $subImage; 
} 

Оно должно быть:

protected $subImages; 

public function getSubImages() 
{ 
    return $this->subImages; 
} 
public function addSubImage(KitchenSubImage $subImage) 
{ 
    $this->subImages[] = $subImage; 
    $subImage->setKitchen($this); 
} 

Посмотрите, как коллекция ака связи работает в Доктрине ?. Так же, как показывает пример bolg/tags. Поскольку компонент формы обрабатывает коллекцию subImages, он будет вызывать addSubImage для каждого опубликованного KitchenSubImage.

Вышеуказанное изменение может или не может исправить все. Вид сомнения. Если нет:

Скажите, пожалуйста, что у вас есть кухонная форма, прежде чем вы добавили сборку подтипов? Вы можете загрузить/сохранить/получить главное изображение? Если нет, закомментируйте $ builder-> add ('subImage', 'collection' и сосредоточьтесь на кухонном объекте.

После того, как кухня работает, добавьте subImages обратно в форму, но закомментируйте allow_add и сообщите, что происходит ,

=============================================================================================================================================== =====

Что касается обработки вспомогательных изображений, я могу понять некоторые путаницы. Я не реализовал коллекцию изображений сам. Могут быть некоторые ошибки.

Я знаю, что вам нужно вызывать загрузку для каждого дополнительного изображения. загрузка на самом деле несколько вводящее в заблуждение имя. Файл уже находится на вашем сервисе, сидя где-то в каталоге tmp. Загрузка просто перемещает его в постоянное место и сохраняет путь в вашей сущности.

Start, пытаясь это:

if ($form->isValid()) { 
     $kitchen->upload(); 
     foreach($kitchen->getSubImages() as $subImage) 
     { 
      $subImage->upload(); 
     } 
     // really should redirect here but okay for now 
     return $this->render('PWDWebsiteBundle:Pages:home.html.twig'); 
    } 

Это может быть лучше, чтобы петля на подизображений в кухне :: загрузки, но попробовать его в контроллере на данный момент.

+0

Эй, снова! Да, у меня есть кухонная форма, прежде чем я начал внедрять subImages. Я выполнил ваши изменения выше и прокомментировал часть subImages формы. Вот мой класс контроллера с полностью работающей кухней - http://pastebin.com/1MCg5NEL – ritch

+0

Что я не могу понять, как загружать subImages? – ritch

+0

Выполнены изменения, но я не могу получить входной файл Sub Image для отображения? – ritch

Смежные вопросы