我有两个实体
- 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';
}
}
答案 0 :(得分: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);
}
了解一个集合aka关系如何在Doctrine中起作用?就像bolg / tags示例所示。当表单组件处理subImages集合时,它将为每个发布的KitchenSubImage调用addSubImage。
上述更改可能会也可能不会解决所有问题。有点怀疑。如果不是:
请在添加子图像集之前告诉我您的厨房表格是否正常工作?您可以加载/存储/检索主图像吗?如果没有,请注释掉$ builder-&gt; add('subImage','collection',并专注于厨房实体。
一旦厨房工作,将子图像添加回表单,但注释掉allow_add并报告发生的情况。
=============================================== ====
关于如何处理子图像,我可以理解一些混淆。我没有实现我自己的图像集合。可能是一些陷阱。
我知道您需要在每个子图像上调用上传。上传实际上是一个有点误导性的名称。该文件已经位于某个tmp目录中的服务器上。上传只是将其移动到永久位置并将路径存储在您的实体中。
首先尝试:
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');
}
最好循环使用kitchen :: upload中的subImages,但现在在控制器中尝试它。