我有两个实体,Kitchen和KitchenImage。 Kitchens的子图像存储在KitchenImage实体中。
我遇到的问题是没有显示KitchenImage的文件输入框,但是它的标签是?
Twig文件:
<div class="row">
<div class="col-md-12">
{{ form_start(form, {'attr': {'role': 'form'}}) }}
<div class="form-group">
{{ form_label(form.name, 'Title') }}
{{ form_errors(form.name) }}
{{ form_widget(form.name, {'attr': {'class': 'form-control', 'placeholder': 'Enter title' }}) }}
</div>
<div class="row">
<div class="form-group col-md-3">
{{ form_label(form.image, 'Main Image') }}
{{ form_errors(form.image) }}
{{ form_widget(form.image) }}
<p class="help-block">Main Image</p>
</div>
<div class="form-group col-md-3">
{{ form_label(form.images, 'Sub Images') }}
{{ form_errors(form.images) }}
{{ form_widget(form.images) }}
<p class="help-block">Sub Images</p>
</div>
</div>
<div class="form-group">
{{ form_label(form.description) }}
{{ form_errors(form.description) }}
{{ form_widget(form.description, {'attr': {'class': 'form-control' }}) }}
</div>
<button type="submit" class="btn btn-default">Submit</button>
{{ form_end(form) }}
</div>
</div>
控制器
<?php
namespace PWD\AdminBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use PWD\AdminBundle\Form\Type\KitchenType;
use PWD\AdminBundle\Form\Type\KitchenImageType;
use PWD\WebsiteBundle\Entity\Kitchen;
use PWD\WebsiteBundle\Entity\KitchenImage;
class KitchenController extends Controller
{
public function addAction(Request $request)
{
$kitchen = new Kitchen();
$form = $this->createForm(new KitchenType(), $kitchen);
$form->handleRequest($request);
if ($form->isValid())
{
return "Yeah!";
}
return $this->render('PWDAdminBundle:Pages:add-kitchen.html.twig', array(
'form' => $form->createView(),
));
}
}
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', 'text')
->add('description', 'textarea')
->add('image', 'file')
->add('images', 'collection', array(
'type' => new KitchenImageType(),
'cascade_validation' => true,
));
}
public function getName()
{
return 'kitchen';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'PWD\WebsiteBundle\Entity\Kitchen',
'cascade_validation' => true,
));
}
}
KitchenImageType
<?php
namespace PWD\AdminBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class KitchenImageType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('image', 'file');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'PWD\WebsiteBundle\Entity\KitchenImage',
'cascade_validation' => true,
'allow_add' => true,
));
}
public function getName()
{
return 'kitchenimage';
}
}
KitchenImage实体
<?php
namespace PWD\WebsiteBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;
/**
* KitchenImage
*
* @ORM\Table(name="kitchen_image")
* @ORM\Entity
*/
class KitchenImage
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @Assert\File(maxSize="6000000")
* @Assert\Image(
* minWidth = 800,
* maxWidth = 800,
* minHeight = 467,
* maxHeight = 467
* )
*/
public $image;
/**
* @ORM\ManyToOne(targetEntity="Kitchen", inversedBy="image")
* @ORM\JoinColumn(name="kitchen_id", referencedColumnName="id")
*/
protected $kitchen;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
public $path;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set image
*
* @param UploadedFile $file
*/
public function setImage(UploadedFile $image = null)
{
$this->image = $image;
}
/**
* Get image
*
* @return string
*/
public function getImage()
{
return $this->image;
}
/**
* Set kitchen
*
* @param \PWD\WebsiteBundle\Entity\Kitchen $kitchen
* @return KitchenImage
*/
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;
}
public function getAbsolutePath()
{
return null === $this->path
? null
: $this->getUploadRootDir().'/'.$this->path;
}
public function getWebPath()
{
return null === $this->path
? null
: $this->getUploadDir().'/'.$this->path;
}
protected function getUploadRootDir()
{
// the absolute directory path where uploaded
// documents should be saved
return __DIR__.'/../../../../web/'.$this->getUploadDir();
}
protected function getUploadDir()
{
// get rid of the __DIR__ so it doesn't screw up
// when displaying uploaded doc/image in the view.
return 'uploads/our-work';
}
public function upload()
{
// the file property can be empty if the field is not required
if (null === $this->getImage()) {
return;
}
// use the original file name here but you should
// sanitize it at least to avoid any security issues
// move takes the target directory and then the
// target filename to move to
$this->getImage()->move(
$this->getUploadRootDir(),
$this->getImage()->getClientOriginalName()
);
// set the path property to the filename where you've saved the file
$this->path = $this->getImage()->getClientOriginalName();
// clean up the file property as you won't need it anymore
$this->image = null;
}
/**
* Set path
*
* @param string $path
* @return KitchenImage
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* Get path
*
* @return string
*/
public function getPath()
{
return $this->path;
}
}
厨房实体
<?php
namespace PWD\WebsiteBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;
/**
* @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\NotNull()
* @Assert\Image(
* minWidth = 800,
* maxWidth = 800,
* minHeight = 467,
* maxHeight = 467
* )
*/
protected $image;
/**
* @ORM\OneToMany(targetEntity="KitchenImage", mappedBy="kitchen")
* @Assert\Type(type="PWD\WebsiteBundle\Entity\KitchenImage")
*/
protected $images;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
public $imagePath;
public function __construct()
{
$this->images = new ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return Kitchen
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set description
*
* @param string $description
* @return Kitchen
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set image
*
* @param UploadedFile $image
* @return Kitchen
*/
public function setImage(UploadedFile $image = null)
{
$this->image = $image;
}
/**
* Get image
*
* @return string
*/
public function getImage()
{
return $this->image;
}
/**
* Add images
*
* @param \PWD\WebsiteBundle\Entity\KitchenImage $images
* @return Kitchen
*/
public function addImage(\PWD\WebsiteBundle\Entity\KitchenImage $images)
{
$this->images[] = $images;
return $this;
}
/**
* Remove images
*
* @param \PWD\WebsiteBundle\Entity\KitchenImage $images
*/
public function removeImage(\PWD\WebsiteBundle\Entity\KitchenImage $images)
{
$this->images->removeElement($images);
}
/**
* Get images
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getImages()
{
return $this->images;
}
/**
* Get absolute path
*/
public function getAbsolutePath()
{
return null === $this->imagePath
? null
: $this->getUploadRootDir().'/'.$this->imagePath;
}
/**
* Get web path
*/
public function getWebPath()
{
return null === $this->path
? null
: $this->getUploadDir().'/'.$this->imagePath;
}
/**
* Get upload root directory
*/
protected function getUploadRootDir()
{
return __DIR__.'/../../../../web/'.$this->getUploadDir();
}
/**
* Get upload directory
*/
protected function getUploadDir()
{
return 'uploads/our-work';
}
/**
* Upload image
*/
public function upload()
{
// The file property can be empty if the field is not required
if (null === $this->getImage()) {
return;
}
// move takes the target directory and then the
// target filename to move to
$this->getImage()->move(
$this->getUploadRootDir(),
$this->getImage()->getClientOriginalName()
);
// set the path property to the filename where you've saved the file
$this->imagePath = $this->getImage()->getClientOriginalName();
// clean up the file property as you won't need it anymore
$this->image = null;
}
/**
* Set imagePath
*
* @param string $imagePath
* @return Kitchen
*/
public function setImagePath($imagePath)
{
$this->imagePath = $imagePath;
return $this;
}
/**
* Get imagePath
*
* @return string
*/
public function getImagePath()
{
return $this->imagePath;
}
}
答案 0 :(得分:0)
我很确定问题是你的KitchenImageType中有allow_add
,它应该在你的KitchenType中的集合上
class KitchenType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text')
->add('description', 'textarea')
->add('image', 'file')
->add('images', 'collection', array(
'type' => new KitchenImageType(),
'cascade_validation' => true,
'allow_add' => true, // *** Need this here, remove it from KitchenImageType
));
}
可能还有其他问题,但我认为就是这样。您可能希望仔细阅读本书中的示例:http://symfony.com/doc/current/cookbook/form/form_collections.html。要让新东西发挥作用,需要做很多事情。
==================================
要回复关于添加厨房图像以进行测试的评论,只需
public function addAction(Request $request)
{
$kitchen = new Kitchen();
$kitchen->addImage(new KitchenImage());
$form = $this->createForm(new KitchenType(), $kitchen);
图像和图像属性有点令人困惑。稍后您可能希望将图像重命名为subImages,并将图像重命名为mainImage,以保证清晰。但它仍然应该有效。
==================================
它是你的厨房实体,你需要这样才能保持正确的事情:
// Note that your are only passing one image at a time to argument is $image not $images
public function addImage(\PWD\WebsiteBundle\Entity\KitchenImage $kitchenImage)
{
$this->images[] = $kitchenImage;
$kitchenImage->setKitchen($this); // *** Need this for persisting
return $this;
}
=========================================
当你经历一个故障排除过程只是意识到基本问题完全不同时,这总是很有趣。您需要了解文件上传的工作原理,不仅仅是在Symfony / Doctrine中,而是在Web上。
有了一个新项目,请仔细阅读并实施:
http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html
http://symfony.com/doc/current/reference/forms/types/file.html
一旦您了解了如何上传文件(即图像)以及如何存储它们(数据库中的路径,文件本身位于Web服务器上的某个位置),您就可以回到厨房用品并正确处理图像。一旦你这样做,只需让你的主厨房图像工作,然后添加一组子图像。