我需要实体Project
和Image
。它们由OneToOne
关系链接。
以下是项目中的属性定义:
/**
* @Exclude
* @ORM\OneToOne(targetEntity="SensoBundle\Entity\Image", cascade={"persist", "remove"})
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
*/
private $image;
这是图像实体
<?php
namespace SensoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Image
*
* @ORM\Table(name="image")
* @ORM\HasLifecycleCallbacks()
* @ORM\Entity(repositoryClass="SensoBundle\Repository\ImageRepository")
*/
class Image
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="fileName", type="string", length=255)
*/
private $fileName;
/**
* @var string
*
* @ORM\Column(name="parentType", type="string", length=255, nullable=true)
*/
private $parentType;
private $tempFilename;
private $file;
private $fileNamePrefix;
private $fileExtension;
private $hashForName;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set fileName
*
* @param string $fileName
* @return Image
*/
public function setFileName($fileName)
{
$this->fileName = $fileName;
return $this;
}
/**
* Get fileName
*
* @return string
*/
public function getFileName()
{
return $this->fileName;
}
public function getFile()
{
return $this->file;
}
public function setFile($file = null)
{
$this->file = $file;
if (null !== $this->fileName) {
$this->tempFilename = $this->fileName;
$this->fileName = null;
}
}
public function getUploadDir()
{
return '/uploads/img';
}
public function getUploadRootDir()
{
return __DIR__ . '/../../../web' . $this->getUploadDir();
}
/**
* @ORM\PrePersist()
* @ORM\PreUpdate()
*/
public function preUpload()
{
if (null === $this->file) {
return;
}
if (null !== $this->fileName) {
$this->tempFilename = $this->fileName;
}
$this->fileExtension = $this->file->guessExtension();
}
/**
* @ORM\PostPersist()
* @ORM\PostUpdate()
*/
public function upload()
{
if (null === $this->file) {
return;
}
if (null !== $this->tempFilename) {
$oldFile = $this->getUploadRootDir() . '/' . $this->tempFilename;
if (file_exists($oldFile)) {
unlink($oldFile);
}
}
$this->file->move(
$this->getUploadRootDir(),
$this->fileName
);
}
/**
* @ORM\PreRemove()
*/
public function preRemoveUpload()
{
$this->tempFilename = $this->getUploadRootDir() . '/' . $this->fileName;
}
/**
* @ORM\PostRemove()
*/
public function removeUplaod()
{
if (file_exists($this->tempFilename)) {
unlink($this->tempFilename);
}
}
public function setFileNamePrefix($prefix)
{
$this->fileNamePrefix = $prefix;
}
public function setHashForname($hash)
{
$this->hashForName = $hash;
}
/**
* Set parentType
*
* @param string $parentType
* @return Image
*/
public function setParentType($parentType)
{
$this->parentType = $parentType;
return $this;
}
/**
* Get parentType
*
* @return string
*/
public function getParentType()
{
return $this->parentType;
}
public function getFileExtension() {
return $this->fileExtension;
}
public function getFilenamePrefix() {
return $this->fileNamePrefix;
}
}
这是控制器的一部分:
/**
* @Route("/project/{id}/presentation/edit", name="project_presentation_edit")
* @Method({"GET", "POST"})
*/
public function editPresentationAction(Request $request, $id)
{
$entity = $this->get('creasenso.project_repo')->find($id);
if (!$entity) {
throw $this->createNotFoundException('The project does not exist');
}
$this->denyAccessUnlessGranted('editProject', $entity);
$form = $this->createForm('CreasensoBundle\Form\Project\ProjectPresentationType', $entity);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
$this->get('session')->getFlashBag()->add('success', 'project.presentation.feedback');
$redirectRoute = ($request->request->get('nextSubmit')) ? 'project_details_edit' : 'project_presentation_edit';
return $this->redirectToRoute($redirectRoute, array('id' => $id));
}
return $this->render('CreasensoBundle:project:editPresentation.html.twig', array(
'form' => $form->createView(),
'entity' => $entity
));
}
这是上面控制器中调用的表单
<?php
// src/Infinite/InvoiceBundle/Form/Type/InvoiceType.php
namespace CreasensoBundle\Form\Project;
use Infinite\FormBundle\Form\Type\PolyCollectionType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ProjectPresentationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('image', 'SensoBundle\Form\Image\ImageSimpleEditType', array(
'label' => 'Cover',
'attr' => array(
'help_text' => 'project.cover.help'
),
'display_image_format' => 'projectCoverSmall',
'imagesConstraints' => array(
'minWidth' => 300
)
))
->add('trans_name_fr', 'SensoBundle\Form\Type\FieldTranslationType', array(
'mapped' => false,
'cascade_validation' => true,
'fieldName' => 'name',
'fieldLocale' => 'fr',
'fieldOptions' => array(
'label' => 'French name',
'required' => true
)
))
->add('trans_name', 'SensoBundle\Form\Type\FieldTranslationType', array(
'mapped' => false,
'cascade_validation' => true,
'fieldName' => 'name',
'fieldLocale' => 'en',
'fieldOptions' => array(
'label' => 'English name',
'required' => true
)
))
;
}
public function getBlockPrefix()
{
return 'projectContent';
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'CreasensoBundle\Entity\Project'
));
}
}
这是我的通用图像实体字段
<?php
namespace SensoBundle\Form\Image;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Validator\Constraints\Image as ImageValidator;
use SensoBundle\Entity\Image;
class ImageSimpleEditType extends AbstractType
{
private $imageUrl = null;
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(FormEvents::POST_SET_DATA, function ($event) use ($builder, $options) {
$form = $event->getForm();
$imageFieldParams = array(
'label' => false,
'display_image_format' => $options['display_image_format'],
'required' => false
);
if (!empty($options['imagesConstraints'])) {
// Image format
$constraints = $options['imagesConstraints'];
$validatorParams = array();
if (!empty($constraints['format'])) {
switch ($constraints['format']) {
case 'square':
$squareErrMsg = "image.edit.squareError";
$validatorParams['allowSquare'] = true;
$validatorParams['allowLandscape'] = false;
$validatorParams['allowPortrait'] = false;
$validatorParams['allowLandscapeMessage'] = $squareErrMsg;
$validatorParams['allowPortraitMessage'] = $squareErrMsg;
break;
case 'landscape':
$landscapeErrMsg = "image.edit.landscapeError";
$validatorParams['allowSquare'] = false;
$validatorParams['allowLandscape'] = true;
$validatorParams['allowPortrait'] = false;
$validatorParams['allowLandscapeMessage'] = $landscapeErrMsg;
$validatorParams['allowPortraitMessage'] = $landscapeErrMsg;
break;
case 'portrait':
$portraitErrMsg = "image.edit.portraitError";
$validatorParams['allowSquare'] = false;
$validatorParams['allowLandscape'] = false;
$validatorParams['allowPortrait'] = true;
$validatorParams['allowLandscapeMessage'] = $portraitErrMsg;
$validatorParams['allowPortraitMessage'] = $portraitErrMsg;
break;
}
// Min width
if (!empty($constraints['minWidth'])) {
$validatorParams['minWidth'] = $constraints['minWidth'];
}
}
$imageFieldParams['constraints'] = new ImageValidator($validatorParams);
}
$form->add('file', 'SensoBundle\Form\Image\ImageInputType', $imageFieldParams);
});
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'SensoBundle\Entity\Image',
'display_image_format' => 'original',
'imagesConstraints' => null
));
}
public function getBlockPrefix()
{
return 'sensoImage';
}
}
最后,这是我的通用图像文件输入(用于图像实体形式)
<?php
namespace SensoBundle\Form\Image;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use SensoBundle\Entity\Image;
use Symfony\Component\Validator\Constraints\Image as ImageValidator;
class ImageInputType extends AbstractType
{
private $imageManager;
public function __construct($imageManager)
{
$this->imageManager = $imageManager;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
}
//
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['image_url'] = null;
$imageEntity = $form->getParent()->getData();
if ($imageEntity) {
$this->imageManager->setEntity($imageEntity);
$view->vars['image_url'] = $this->imageManager->getRelativeUrl();
}
$view->vars['display_image_format'] = $options['display_image_format'];
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'display_image_format' => 'original',
'format' => null
));
}
public function getBlockPrefix()
{
return 'sensoImageInput';
}
public function getParent()
{
return 'Symfony\Component\Form\Extension\Core\Type\FileType';
}
}
我的表单结构就像那样
我的问题是即使没有上传文件也会创建图像实体。
我希望能够使用这个“功能”创建一个新项目:
感谢您的帮助。