Symfony 2.5.6-在自定义表单类型中引发意外的TypeException


Symfony 2.5.6 - UnexpectedTypeException being thrown in a custom form type

我有以下表单类型:

class GalleryImageType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('thumb', new GalleryThumbnailImage(), array('label' => 'Thumbnail Image'))
            ->add('full', new GalleryFullSizeImage(), array('label' => 'Full Size Image'));
    }
    public function getName()
    {
        return 'galleryImage';
    }
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array('data_class' => 'MajorProductions'SewingDiva'SiteBundle'Entity'GalleryImage'));
    }
}

以及以下实体:

/**
 * @ORM'Entity
 * @ORM'HasLifecycleCallbacks
 * @ORM'Table(name="GalleryImage", indexes={@ORM'Index(name="id_idx", columns={"id"})})
 */
class GalleryImage
{
    /**
     * @ORM'Id
     * @ORM'Column(type="integer")
     * @ORM'GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @ORM'OneToOne(targetEntity="GalleryThumbnailImage", mappedBy="galleryImage")
     */
    private $thumb;
    /**
     * @ORM'OneToOne(targetEntity="GalleryFullSizeImage", mappedBy="galleryImage")
     */
    private $full;
    /**
     * @ORM'Column(name="lastModified", type="datetime", nullable=true)
     */
    private $lastModified;
    public function getId()
    {
        return $this->id;
    }
    public function setId($id)
    {
        $this->id = $id;
    }
    /**
     * @return GalleryFullSizeImage
     */
    public function getFull()
    {
        return $this->full;
    }
    /**
     * @param GalleryFullSizeImage $full
     */
    public function setFull(Full $full)
    {
        $this->full = $full;
    }
    /**
     * @return GalleryThumbnailImage
     */
    public function getThumb()
    {
        return $this->thumb;
    }
    /**
     * @param GalleryThumbnailImage $thumb
     */
    public function setThumb(Thumb $thumb)
    {
        $this->thumb = $thumb;
    }
    /**
     * @return 'DateTime
     */
    public function getLastModified()
    {
        return $this->lastModified;
    }
    /**
     * @param 'DateTime $lastModified
     */
    public function setLastModified('DateTime $lastModified)
    {
        $this->lastModified = $lastModified;
    }
}
// ----
/**
 * @ORM'Entity
 * @ORM'HasLifecycleCallbacks
 * @ORM'Table(name="GalleryFullSizeImage", indexes={@ORM'Index(name="id_idx", columns={"id"})})
 */
class GalleryFullSizeImage
{
    /**
     * @ORM'Id
     * @ORM'Column(type="integer")
     * @ORM'GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @ORM'OneToOne(targetEntity="GalleryImage", inversedBy="full")
     * @ORM'JoinColumn(name="galleryImageId", referencedColumnName="id", onDelete="SET NULL")
     */
    private $galleryImage;
    /**
     * @ORM'Column(type="string", length=255)
     */
    private $path;
    /**
     * @Assert'Image(maxSize="6000000")
     */
    private $file;
    private $tmp;
    public function getId()
    {
        return $this->id;
    }
    public function setId($id)
    {
        $this->id = $id;
    }
    public function getGalleryImage()
    {
        return $this->galleryImage;
    }
    public function setGalleryImage(GalleryImage $galleryImage)
    {
        $this->galleryImage = $galleryImage;
    }
    public function getWebPath()
    {
        return null === $this->path ? null : $this->getUploadRootDir() . '/' . $this->path;
    }
    protected function getUploadRootDir()
    {
        // the absolute directory path where uploaded
        // documents should be saved
        return __DIR__ . '/../../../../web/' . $this->getUploadDir() . '/full';
    }
    protected function getUploadDir()
    {
        // get rid of the __DIR__ so it doesn't screw up
        // when displaying uploaded doc/image in the view.
        return 'uploads/gallery';
    }
    /**
     * Sets file.
     *
     * @param UploadedFile $file
     */
    public function setFile(UploadedFile $file = null)
    {
        $this->file = $file;
        // check if we have an old image path
        if (is_file($this->getAbsolutePath())) {
            // store the old name to delete after the update
            $this->tmp = $this->getAbsolutePath();
        } else {
            $this->path = 'initial';
        }
    }
    /**
     * Returns file
     *
     * @return mixed
     */
    public function getFile()
    {
        return $this->file;
    }
    /**
     * @ORM'PrePersist()
     * @ORM'PreUpdate()
     */
    public function preUpload()
    {
        if (null !== $this->getFile()) {
            $this->path = $this->getFile()->guessExtension();
        }
    }
    /**
     * @ORM'PostPersist()
     * @ORM'PostUpdate()
     */
    public function upload()
    {
        if (null === $this->getFile()) {
            return;
        }
        // check if we have an old image
        if (isset($this->tmp)) {
            // delete the old image
            unlink($this->tmp);
            // clear the temp image path
            $this->tmp = null;
        }
        $this->getFile()->move(
            $this->getUploadRootDir(),
            $this->id . '.' . $this->getFile()->guessExtension()
        );
        $this->setFile(null);
        $this->galleryImage->setLastModified(new 'DateTime(null));
    }
    /**
     * @ORM'PreRemove()
     */
    public function storeFilenameForRemove()
    {
        $this->tmp = $this->getAbsolutePath();
    }
    /**
     * @ORM'PostRemove()
     */
    public function removeUpload()
    {
        if (isset($this->tmp)) {
            unlink($this->tmp);
            $this->galleryImage->setLastModified(new 'DateTime(null));
        }
    }
    public function getAbsolutePath()
    {
        return null === $this->path ? null : $this->getUploadRootDir() . '/' . $this->id . '.' . $this->path;
    }
}
// ----
/**
 * @ORM'Entity
 * @ORM'HasLifecycleCallbacks
 * @ORM'Table(name="GalleryThumbnailImage", indexes={@ORM'Index(name="id_idx", columns={"id"})})
 */
class GalleryThumbnailImage
{
    /**
     * @ORM'Id
     * @ORM'Column(type="integer")
     * @ORM'GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @ORM'OneToOne(targetEntity="GalleryImage", inversedBy="thumb")
     * @ORM'JoinColumn(name="galleryImageId", referencedColumnName="id", onDelete="SET NULL")
     */
    private $galleryImage;
    /**
     * @ORM'Column(type="string", length=255)
     */
    private $path;
    /**
     * @Assert'Image(maxSize="6000000")
     */
    private $file;
    private $tmp;
    public function getId()
    {
        return $this->id;
    }
    public function setId($id)
    {
        $this->id = $id;
    }
    public function getGalleryImage()
    {
        return $this->galleryImage;
    }
    public function setGalleryImage(GalleryImage $galleryImage)
    {
        $this->galleryImage = $galleryImage;
    }
    public function getWebPath()
    {
        return null === $this->path ? null : $this->getUploadRootDir() . '/' . $this->path;
    }
    protected function getUploadRootDir()
    {
        // the absolute directory path where uploaded
        // documents should be saved
        return __DIR__ . '/../../../../web/' . $this->getUploadDir() . '/thumbs';
    }
    protected function getUploadDir()
    {
        // get rid of the __DIR__ so it doesn't screw up
        // when displaying uploaded doc/image in the view.
        return 'uploads/gallery';
    }
    /**
     * Sets file.
     *
     * @param UploadedFile $file
     */
    public function setFile(UploadedFile $file = null)
    {
        $this->file = $file;
        // check if we have an old image path
        if (is_file($this->getAbsolutePath())) {
            // store the old name to delete after the update
            $this->tmp = $this->getAbsolutePath();
        } else {
            $this->path = 'initial';
        }
    }
    /**
     * Returns file
     *
     * @return mixed
     */
    public function getFile()
    {
        return $this->file;
    }
    /**
     * @ORM'PrePersist()
     * @ORM'PreUpdate()
     */
    public function preUpload()
    {
        if (null !== $this->getFile()) {
            $this->path = $this->getFile()->guessExtension();
        }
    }
    /**
     * @ORM'PostPersist()
     * @ORM'PostUpdate()
     */
    public function upload()
    {
        if (null === $this->getFile()) {
            return;
        }
        // check if we have an old image
        if (isset($this->tmp)) {
            // delete the old image
            unlink($this->tmp);
            // clear the temp image path
            $this->tmp = null;
        }
        $this->getFile()->move(
            $this->getUploadRootDir(),
            $this->id . '.' . $this->getFile()->guessExtension()
        );
        $this->setFile(null);
        $this->galleryImage->setLastModified(new 'DateTime(null));
    }
    /**
     * @ORM'PreRemove()
     */
    public function storeFilenameForRemove()
    {
        $this->tmp = $this->getAbsolutePath();
    }
    /**
     * @ORM'PostRemove()
     */
    public function removeUpload()
    {
        if (isset($this->tmp)) {
            unlink($this->tmp);
            $this->galleryImage->setLastModified(new 'DateTime(null));
        }
    }
    public function getAbsolutePath()
    {
        return null === $this->path ? null : $this->getUploadRootDir() . '/' . $this->id . '.' . $this->path;
    }
}

当我试图查看表单本身时,我从UnexpectedTypeException:收到以下错误消息

给定时应为类型为"string或Symfony''Component''Form''FormTypeInterface"、"MajorProductions''SewingDiva''SiteBundle''Entity''GalleryThumbnailImage"的参数

因此,我的GalleryThumbnailImage字段的FormBuilder添加让它窒息,认为它应该由一个字符串而不是那个对象支持。然而,我真的不知道它为什么要这么做。可能是因为我在GalleryImage中使用了命名空间别名(Thumb代替GalleryThumbnailImageFull代替GalleryFullSizeImage)吗?还是我错过了一些显而易见的东西?


编辑:即使为GalleryFullSizeImageGalleryThumbnailImage:创建了表单类型,问题仍然存在

namespace MajorProductions'SewingDiva'SiteBundle'Form'Type;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
class GalleryFullSizeImageType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('file', 'file');
    }
    public function getName()
    {
        return 'galleryFullSizeImage';
    }
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array('data_class' => 'MajorProductions'SewingDiva'SiteBundle'Entity'GalleryFullSizeImage'));
    }
}
// ----
namespace MajorProductions'SewingDiva'SiteBundle'Form'Type;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
class GalleryThumbnailImageType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('file', 'file');
    }
    public function getName()
    {
        return 'galleryThumbnailImage';
    }
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array('data_class' => 'MajorProductions'SewingDiva'SiteBundle'Entity'GalleryThumbnailImage'));
    }
}

请注意,在我的代码中写入// ----的地方,它表示一个文件的结束和另一个文件开始。考虑到我的实体代码的长度和所有的Doctrine注释,我想我可以通过将单个类的代码放在相同的代码块中来节省一些垂直空间。

您使用:

$builder
    ->add('thumb', new GalleryThumbnailImage(), array('label' => 'Thumbnail Image'))
    ->add('full', new GalleryFullSizeImage(), array('label' => 'Full Size Image'));

让我们回顾一下FormBuilder#add()的论点是什么:public function add($child, $type = null, array $options = array())。您似乎传递了一个实体,而不是$type。这里要传递的类是GalleryThumbnailImageTypeGalleryFullSizeImageType。这些类确实实现了FormTypeInterface,所以一切都很好!

您需要使用的代码:

$builder
    ->add('thumb', new GalleryThumbnailImageType(), array('label' => 'Thumbnail Image'))
    ->add('full', new GalleryFullSizeImageType(), array('label' => 'Full Size Image'));