Embed Symfony file form - php

I want to embed a form (ImageType) into another (VideoFileType) in Symfony. My first form contains a file input. Basically, it's an image that will uploaded and then resized according to many presets already defined.
My second form will embed the ImageType form. The second form is a VideoFileType form which contains the ImageType form. Basically, the ImageType will act as a thumbnail for the video file. The VideoFileType will also contain a second file input to upload the videoFile and finally a select box to select the corresponding VideoPreset.
So to recap, the VideoFileType will embed an ImageType.
My class structure is similar. I have a VideoFile which has a Thumbnail attribute that is an Image class
When I show only the ImageType and upload an image, everything works perfectly fine.
ImageType:
class ImageType extends AbstractType
{
private $imageManager;
public function __construct(ImageManager $imageManager) {
$this->imageManager = $imageManager;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('file', 'file');
$builder->addEventListener(
FormEvents::POST_SUBMIT,
array($this, 'onPostSetData')
);
}
public function getDefaultOptions(array $options) {
return array('data_class' => 'OSC\MediaBundle\Entity\Image');
}
public function onPostSetData(FormEvent $event) {
$image = $event->getData();
$form = $event->getForm();
//We need here to update the video file with the new content
$image = $this->imageManager->uploadImage($image);
$event->setData($image);
}
public function getName()
{
return 'image';
}
}
VideoFileType
class VideoFileType extends AbstractType
{
public $container;
public $videoPresets = [];
public function __construct(Container $container) {
$this->container = $container;
$videoPresets = $container->getParameter('osc_media.video.presets');
foreach ($videoPresets as $key => $videoPreset) {
array_push($this->videoPresets, $key);
}
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('thumbnail', new ImageType($this->container->get('osc_media.manager.image')));
$builder->add('file', 'file');
$builder->add('videoPreset', 'choice', array(
'choices' => $this->videoPresets,
'multiple' => false,
'required' => true
));
$builder->addEventListener(
FormEvents::POST_SUBMIT,
array($this, 'onPostSetData')
);
$builder->add('save', 'submit');
}
public function onPostSetData(FormEvent $event) {
$videoFile = $event->getData();
$form = $event->getForm();
}
public function getDefaultOptions(array $options) {
return array('data_class' => 'OSC\MediaBundle\Entity\VideoFile');
}
public function getName()
{
return 'video_file';
}
}
VideoFile
class VideoFile
{
protected $file;
public function setfile(File $file = null)
{
$this->file = $file;
if ($file) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTime('now');
}
}
/**
* #return File
*/
public function getFile()
{
return $this->file;
}
public function __construct() {
$this->thumbnail = new Image();
}
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $name;
/**
* #var string
*/
private $filename;
/**
* #var integer
*/
private $position;
/**
* #var string
*/
private $extension;
/**
* #var integer
*/
private $size;
/**
* #var string
*/
private $videoPreset;
/**
* #var integer
*/
private $duration;
/**
* #var \DateTime
*/
private $createdAt;
/**
* #var \DateTime
*/
private $updatedAt;
/**
* #var string
*/
private $height;
/**
* #var string
*/
private $width;
/**
* #var \OSC\MediaBundle\Entity\Image
*/
private $thumbnail;
/**
* #var \OSC\MediaBundle\Entity\Video
*/
private $video;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return VideoFile
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set filename
*
* #param string $filename
* #return VideoFile
*/
public function setFilename($filename)
{
$this->filename = $filename;
return $this;
}
/**
* Get filename
*
* #return string
*/
public function getFilename()
{
return $this->filename;
}
/**
* Set position
*
* #param integer $position
* #return VideoFile
*/
public function setPosition($position)
{
$this->position = $position;
return $this;
}
/**
* Get position
*
* #return integer
*/
public function getPosition()
{
return $this->position;
}
/**
* Set extension
*
* #param string $extension
* #return VideoFile
*/
public function setExtension($extension)
{
$this->extension = $extension;
return $this;
}
/**
* Get extension
*
* #return string
*/
public function getExtension()
{
return $this->extension;
}
/**
* Set size
*
* #param integer $size
* #return VideoFile
*/
public function setSize($size)
{
$this->size = $size;
return $this;
}
/**
* Get size
*
* #return integer
*/
public function getSize()
{
return $this->size;
}
/**
* Set videoPreset
*
* #param string $videoPreset
* #return VideoFile
*/
public function setVideoPreset($videoPreset)
{
$this->videoPreset = $videoPreset;
return $this;
}
/**
* Get videoPreset
*
* #return string
*/
public function getVideoPreset()
{
return $this->videoPreset;
}
/**
* Set duration
*
* #param integer $duration
* #return VideoFile
*/
public function setDuration($duration)
{
$this->duration = $duration;
return $this;
}
/**
* Get duration
*
* #return integer
*/
public function getDuration()
{
return $this->duration;
}
/**
* Set createdAt
*
* #param \DateTime $createdAt
* #return VideoFile
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt
*
* #return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set updatedAt
*
* #param \DateTime $updatedAt
* #return VideoFile
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* #return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* Set height
*
* #param string $height
* #return VideoFile
*/
public function setHeight($height)
{
$this->height = $height;
return $this;
}
/**
* Get height
*
* #return string
*/
public function getHeight()
{
return $this->height;
}
/**
* Set width
*
* #param string $width
* #return VideoFile
*/
public function setWidth($width)
{
$this->width = $width;
return $this;
}
/**
* Get width
*
* #return string
*/
public function getWidth()
{
return $this->width;
}
/**
* Set thumbnail
*
* #param \OSC\MediaBundle\Entity\Image $thumbnail
* #return VideoFile
*/
public function setThumbnail(\OSC\MediaBundle\Entity\Image $thumbnail = null)
{
$this->thumbnail = $thumbnail;
return $this;
}
/**
* Get thumbnail
*
* #return \OSC\MediaBundle\Entity\Image
*/
public function getThumbnail()
{
return $this->thumbnail;
}
/**
* Set video
*
* #param \OSC\MediaBundle\Entity\Video $video
* #return VideoFile
*/
public function setVideo(\OSC\MediaBundle\Entity\Video $video = null)
{
$this->video = $video;
return $this;
}
/**
* Get video
*
* #return \OSC\MediaBundle\Entity\Video
*/
public function getVideo()
{
return $this->video;
}
}
Image Class
class Image
{
protected $file;
public function setfile(File $file = null)
{
$this->file = $file;
if ($file) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTime('now');
}
}
/**
* #return File
*/
public function getFile()
{
return $this->file;
}
/**
* #var integer
*/
private $id;
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $imageFiles;
/**
* Constructor
*/
public function __construct()
{
$this->imageFiles = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Add imageFiles
*
* #param \OSC\MediaBundle\Entity\ImageFile $imageFiles
* #return Image
*/
public function addImageFile(\OSC\MediaBundle\Entity\ImageFile $imageFiles)
{
$this->imageFiles[] = $imageFiles;
return $this;
}
/**
* Remove imageFiles
*
* #param \OSC\MediaBundle\Entity\ImageFile $imageFiles
*/
public function removeImageFile(\OSC\MediaBundle\Entity\ImageFile $imageFiles)
{
$this->imageFiles->removeElement($imageFiles);
}
/**
* Get imageFiles
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getImageFiles()
{
return $this->imageFiles;
}
}
ImageFile
class ImageFile
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $name;
/**
* #var string
*/
private $filename;
/**
* #var string
*/
private $extension;
/**
* #var string
*/
private $size;
/**
* #var string
*/
private $imagePreset;
/**
* #var \DateTime
*/
private $createdAt;
/**
* #var \DateTime
*/
private $updatedAt;
/**
* #var string
*/
private $height;
/**
* #var string
*/
private $width;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return ImageFile
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set filename
*
* #param string $filename
* #return ImageFile
*/
public function setFilename($filename)
{
$this->filename = $filename;
return $this;
}
/**
* Get filename
*
* #return string
*/
public function getFilename()
{
return $this->filename;
}
/**
* Set extension
*
* #param string $extension
* #return ImageFile
*/
public function setExtension($extension)
{
$this->extension = $extension;
return $this;
}
/**
* Get extension
*
* #return string
*/
public function getExtension()
{
return $this->extension;
}
/**
* Set size
*
* #param string $size
* #return ImageFile
*/
public function setSize($size)
{
$this->size = $size;
return $this;
}
/**
* Get size
*
* #return string
*/
public function getSize()
{
return $this->size;
}
/**
* Set imagePreset
*
* #param string $imagePreset
* #return ImageFile
*/
public function setImagePreset($imagePreset)
{
$this->imagePreset = $imagePreset;
return $this;
}
/**
* Get imagePreset
*
* #return string
*/
public function getImagePreset()
{
return $this->imagePreset;
}
/**
* Set createdAt
*
* #param \DateTime $createdAt
* #return ImageFile
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt
*
* #return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set updatedAt
*
* #param \DateTime $updatedAt
* #return ImageFile
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* #return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* Set height
*
* #param string $height
* #return ImageFile
*/
public function setHeight($height)
{
$this->height = $height;
return $this;
}
/**
* Get height
*
* #return string
*/
public function getHeight()
{
return $this->height;
}
/**
* Set width
*
* #param string $width
* #return ImageFile
*/
public function setWidth($width)
{
$this->width = $width;
return $this;
}
/**
* Get width
*
* #return string
*/
public function getWidth()
{
return $this->width;
}
}
However, when I try to create a VideoFileType form, I get the following error:
The form's view data is expected to be of type scalar, array or an instance of \ArrayAccess, but is an instance of class OSC\MediaBundle\Entity\Image. You can avoid this error by setting the "data_class" option to "OSC\MediaBundle\Entity\Image" or by adding a view transformer that transforms an instance of class OSC\MediaBundle\Entity\Image to scalar, array or an instance of \ArrayAccess.
So, what I want, is the treatment of the ImageFileType (OnPostSetData) to be executed with the same success when embedded in VideoFileType as when used alone.
Then, after completion, I want the Image object to be inserted in the VideoFile as the thumbnail attribute. Afterwards, it should finish the treatment inside VideoFileType's OnPostSetData method.
If it's not feasible, I'll simply recreate ImageType's logic inside the VideoFileType and that is not a big deal. However, I feel that it could be nice if I could reuse the ImageFileType.

I'm not a 100% sure but try adding this function to your ImageTypeclass.
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
....
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'OSC\MediaBundle\Entity\Image'
));
}
And change the configuration for the thumbnail property inside buildForm in class VideoFileType.
$builder->add('thumbnail',
new ImageType($this->container->get('osc_media.manager.image')),
array(
'data_class' => 'OSC\MediaBundle\Entity\Image'
));

This is verry easy if you want to extend formtype,
just do like this:
Define your first form as a service
Extend your second form using getParent method
public function getParent()
{
return 'image';
}
doing like this you have the same fields in ur second form as in first
and you can add some more.

Related

How to get uploadedFile array from PHP form

I am new to PHP. I succeeded in uploading single image to a form and saving it in the database. But when I modify that to upload multiple images, I get an error saying
The form's view data is expected to be an instance of class Symfony\Component\HttpFoundation\File\File, but is a(n) array.
class SatelliteImages
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var array
*/
private $files= array();
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
*Set files
*
* #param UploadedFile[] $files
*/
public function setFiles($files)
{
$this->files = $files;
//return $this;
}
/**
* Get files
*
* #return UploadedFile[]
*/
public function getFiles()
{
return $this->files;
}
/**
* #param satelliteImage[] $images
*
* #return satelliteImage[]
*
*/
public function upload($images){
foreach ($this->getFiles() as $key => $file) {
$images[$key]->setImage(file_get_contents($file));
}
return $images;
}
}
This is the SatelliteImage entity(single image)
class satelliteImage
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var float
*
* #ORM\Column(name="latitude", type="float")
*/
private $latitude;
/**
* #var float
*
* #ORM\Column(name="longitude", type="float")
*/
private $longitude;
/**
* #var string
*
* #ORM\Column(name="image", type="blob", nullable=true))
*/
private $image;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
public $path;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set latitude
*
* #param float $latitude
*
* #return satelliteImage
*/
public function setLatitude($latitude)
{
$this->latitude = $latitude;
return $this;
}
/**
* Get latitude
*
* #return float
*/
public function getLatitude()
{
return $this->latitude;
}
/**
* Set longitude
*
* #param float $longitude
*
* #return satelliteImage
*/
public function setLongitude($longitude)
{
$this->longitude = $longitude;
return $this;
}
/**
* Get longitude
*
* #return float
*/
public function getLongitude()
{
return $this->longitude;
}
/**
* Set image
*
* #param string $image
*
* #return satelliteImage
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
/**
* Get path
*
* #return string
*/
public function getPath()
{
return $this->path;
}
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/documents';
}
/**
* #Assert\File(maxSize="6000000")
*/
private $file;
/**
* Sets file.
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
}
/**
* Get file.
*
* #return UploadedFile
*/
public function getFile()
{
return $this->file;
}
public function upload()
{
// the file property can be empty if the field is not required
if (null === $this->getFile()) {
return;
}
$imgFile=$this->getFile();
$this->setImage(file_get_contents($imgFile));
// clean up the file property as you won't need it anymore
$this->file = null;
}
}
In my controller, how can I create an array of images and pass it to the above function?
/**
* #Route("/uploads", name="upload_images")
*
*/
public function uploadImages(Request $request)
{
$images=new Images();
$form = $this->createForm(ImageFile::class, $images);
$form->handleRequest($request);
$em=$this->getDoctrine()->getManager();
$images->upload(????);
}
ImageFile class:
class ImageFile extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('files', FileType::class, array(
'attr' => array(
'accept' => 'image/*',
'multiple' => 'multiple'
)
))
->add('save',SubmitType::class,array('label'=>'Insert Image','attr'=>array('class'=>'btn btn-primary','style'=>'margin-bottom:15px')))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => SatelliteImages::class
));
}
}
This code right here is a problem:
/**
* #Assert\File(maxSize="60000000")
*/
private $files= array();
You need to fix that. You are asserting it's a file, but then you specify that it's an array!
EDIT #2
Your upload function has a problem too. You are returning the same parameter that you are passing in ($images). So you need to change it like so:
/**
* #param satelliteImage[] $images
*
* #return satelliteImage[]
*
*/
public function upload($images){
foreach ($this->getFiles() as $key => $file) {
$img[$key]->setImage(file_get_contents($file));
}
return $img;
}
EDIT #3
The buildForm function seems ok. In your Controller, I think you need to create the class and load the form like this:
$images = new SatelliteImages();
$form = $this->createFormBuilder($images);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$images = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($images);
$em->flush();
return $this->redirectToRoute('some_path');
}
Can you try it? Not sure if that's the problem or not.
SOLUTION
I managed to resolve previous issue by changing 'FileType' to 'CollectionType' in imageFile class's buildForm() function
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('files', CollectionType::class, array(
'attr' => array(
'accept' => 'image/*',
'multiple' => 'multiple'
)
))
->add('save',SubmitType::class,array('label'=>'Insert Image','attr'=>array('class'=>'btn btn-primary','style'=>'margin-bottom:15px')))
;
}
I also changed the 'files' like this
/**
* #var array
*/
private $files;
public function __construct()
{
$this->files = new ArrayCollection();
}
However, when I do that, the 'browse images' button disappears from the view. Any suggestions to fix that?
I also tried removing the construct() function. When I do that, it gives me an error in the controller saying "invalid argument supplied for foreach"

The file '/tmp/phpAtfqKp' does not exist when uploading Image using Symfony2 Sonata Admin Bundle

I hope you're doing well.
Can anyone help me with this error ? I'm trying to upload an image using doctrine, after the image is uploaded I get The file "/tmp/phpAtfqKp" does not exist. I'm using sonata admin bundle to create the entity.
I know that the image is uploaded because it is found in web/uploads/property and when going to the edit entity page all images are displayed without any problem.
Here is my Image entity:
<?php
namespace Hatch2Web\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
use Hatch2Web\MainBundle\Service\UrlService;
/**
* Images
*
* #ORM\Table(name="image")
* #ORM\Entity(repositoryClass="Hatch2Web\MainBundle\Repository\ImagesRepository")
* #ORM\HasLifecycleCallbacks()
*/
class Image
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255,nullable=true)
*/
private $name;
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime")
*/
private $createdAt;
/**
* #var \DateTime
*
* #ORM\Column(name="updated_at", type="datetime", nullable=true)
*/
private $updated_at;
/**
* #ORM\ManyToOne(targetEntity="Hatch2Web\MainBundle\Entity\Property", inversedBy="images")
*/
private $property;
/**
* #Assert\File(maxSize="50000000",
* mimeTypes = {"image/jpeg", "image/jpg","image/png", "image/gif", "image/x-ms-bmp"},
* mimeTypesMessage = "Please upload a valid Mime Type File")
*
*/
public $file;
/**
*
*
* string
*/
private $dummyUrl;
public function __construct()
{
$this->createdAt = new \DateTime();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Image
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set createdAt
*
* #param \DateTime $createdAt
* #return Image
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt
*
* #return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set property
*
* #param \Hatch2Web\MainBundle\Entity\Property $property
* #return Image
*/
public function setProperty(\Hatch2Web\MainBundle\Entity\Property $property = null)
{
$this->property = $property;
return $this;
}
/**
* Get property
*
* #return \Hatch2Web\MainBundle\Entity\Property
*/
public function getProperty()
{
return $this->property;
}
/** File Upload */
/**
* Get file.
*
* #return UploadedFile
*/
public function getFile()
{
return $this->file;
}
public function getUploadDir()
{
return 'uploads/properties';
}
/**
* Sets file.
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null, $hash)
{
if ($file) {
$this->file = $file;
$this->name = $hash . "." . $file->guessExtension();
}
}
public function getDummyUrl()
{
$object = new UrlService();
$baseUrl = $object->getBaseUrl();
if ($this->getName()) {
return $baseUrl . $this->getUploadDir() . '/' . $this->getName();
}
return $object->getNoImage();
}
/**
* #return mixed
*/
public function getUpdatedAt()
{
return $this->updated_at;
}
/**
* #param mixed $updated_at
*/
public function setUpdatedAt($updated_at)
{
$this->updated_at = $updated_at;
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function preUpload()
{
if (null !== $this->getFile()) {
$filename = sha1($this->getFile()->getClientOriginalName());
$this->name = $filename . '.' . $this->getFile()->guessExtension();
}
}
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
{
if (null === $this->getFile()) {
return;
}
$this->getFile()->move($this->getUploadDir(), $this->name);
$this->file = null;
}
/**
* Lifecycle callback to upload the file to the server
*/
public function lifecycleFileUpload()
{
$this->upload();
}
/**
* #ORM\PreRemove()
*
*
*
*/
public function removeFile()
{
$url = $this->getUploadDir() . '/' . $this->getName();
try {
if (file_exists($url)) {
unlink($url);
}
} catch (\Exception $e) {
return $e->getMessage();
}
}
/**
* Updates the hash value to force the preUpdate and postUpdate events to fire
*/
public function refreshUpdated()
{
$this->setUpdatedAt(new \DateTime());
}
}
And here is a screenshot
enter image description here

Multiple file upload with VlabsMediaBundle in Symfony2

i'm trying to make a multiple upload file on an entity with the vlabsmediaBundle.
So i have an advert who can have many images but each can be linked with only one advert.
I followed the tutorial(tuto) of the bundle but get an error.
Here:
Entity Image.php
namespace MDB\PlatformBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Vlabs\MediaBundle\Entity\BaseFile as VlabsFile;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Image
*
* #ORM\Table()
* #ORM\Entity
*/
class Image extends VlabsFile {
/**
* #var string
*
* #ORM\Column(name="url", type="string", length=255)
*/
private $url;
/**
* #var string
*
* #ORM\Column(name="alt", type="string", length=255)
*/
private $alt;
/**
* #ORM\ManyToOne(targetEntity="MDB\AnnonceBundle\Entity\Annonce", inversedBy="images")
* #ORM\JoinColumn(nullable=true)
*/
private $annonce;
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set url
*
* #param string $url
* #return Image
*/
public function setUrl($url) {
$this->url = $url;
return $this;
}
/**
* Get url
*
* #return string
*/
public function getUrl() {
return $this->url;
}
/**
* Set alt
*
* #param string $alt
* #return Image
*/
public function setAlt($alt) {
$this->alt = $alt;
return $this;
}
/**
* Get alt
*
* #return string
*/
public function getAlt() {
return $this->alt;
}
public function getAnnonce() {
return $this->annonce;
}
public function setAnnonce($annonce) {
$this->annonce = $annonce;
}
/**
* #var string $path
*
* #ORM\Column(name="path", type="string", length=255)
* #Assert\Image()
*/
private $path;
/**
* Set path
*
* #param string $path
* #return Image
*/
public function setPath($path) {
$this->path = $path;
return $this;
}
/**
/**
* Get path
*
* #return string
*/
public function getPath() {
return $this->path;
}
}
Annonce.php (advert enity)
<?php
namespace MDB\AnnonceBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Vlabs\MediaBundle\Annotation\Vlabs;
/**
* Annonce
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="MDB\AnnonceBundle\Entity\AnnonceRepository")
*/
class Annonce {
public function __construct() {
$this->date = new \Datetime();
$this->categories = new ArrayCollection();
$this->images = new ArrayCollection();
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="titre", type="string", length=255)
*/
private $titre;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=255)
*/
private $description;
/**
* #ORM\Column(name="date", type="date")
*/
private $date;
/**
* #var float
*
* #ORM\Column(name="prix", type="float")
*/
private $prix;
/**
* #ORM\ManyToOne(targetEntity="MDB\AdresseBundle\Entity\Ville", inversedBy="annonces")
*/
private $ville;
/**
* #ORM\ManyToMany(targetEntity="MDB\AnnonceBundle\Entity\Category", cascade={"persist"})
*/
private $categories;
/**
* #ORM\ManyToMany(targetEntity="MDB\UserBundle\Entity\User")
*
*/
private $wishlist;
/**
* #var boolean
*
* #ORM\Column(name="telAppear", type="boolean")
*/
private $telAppear;
/**
* #ORM\ManyToOne(targetEntity="MDB\UserBundle\Entity\User", inversedBy="annonces")
* #ORM\JoinColumn(nullable=false)
*/
private $user;
/**
* #var VlabsFile
* #ORM\OneToMany(targetEntity="MDB\PlatformBundle\Entity\Image", mappedBy="annonce")
* #Vlabs\Media(identifier="image_entity", upload_dir="files/images")
* #Assert\Valid()
*/
private $images;
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set titre
*
* #param string $titre
* #return Annonce
*/
public function setTitre($titre) {
$this->titre = $titre;
return $this;
}
/**
* Get titre
*
* #return string
*/
public function getTitre() {
return $this->titre;
}
/**
* Set description
*
* #param string $description
* #return Annonce
*/
public function setDescription($description) {
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription() {
return $this->description;
}
/**
* Set prix
*
* #param float $prix
* #return Annonce
*/
public function setPrix($prix) {
$this->prix = $prix;
return $this;
}
/**
* Get prix
*
* #return float
*/
public function getPrix() {
return $this->prix;
}
public function addCategory(Category $category) {
// Ici, on utilise l'ArrayCollection vraiment comme un tableau
$this->categories[] = $category;
return $this;
}
public function removeCategory(Category $category) {
$this->categories->removeElement($category);
}
public function getCategories() {
return $this->categories;
}
public function getDate() {
return $this->date;
}
public function setDate($date) {
$this->date = $date;
}
public function getWishlist() {
return $this->wishlist;
}
public function setWishlist($wishlist) {
$this->wishlist = $wishlist;
}
public function getVille() {
return $this->ville;
}
public function setVille($ville) {
$this->ville = $ville;
}
public function getTelAppear() {
return $this->telAppear;
}
public function setTelAppear($telAppear) {
$this->telAppear = $telAppear;
}
public function getUser() {
return $this->user;
}
public function setUser($user) {
$this->user = $user;
}
public function addImage(Image $image) {
$this->images[] = $image;
$image->setUser($this);
return $this;
}
public function removeImage(Image $image) {
$this->images->removeElement($image);
}
public function getImages() {
return $this->images;
}
}
config.yml
vlabs_media:
image_cache:
cache_dir: files/c
mapping:
image_entity:
class: MDB\PlatformBundle\Entity\Image
AnnonceSellType.php
<?php
namespace MDB\AnnonceBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use MDB\PlatformBundle\Form\ImageType;
class AnnonceSellType extends AbstractType {
private $arrayListCat;
public function __construct( $arrayListCat)
{
$this->arrayListCat = $arrayListCat;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->remove('wishlist')
->remove('date')
->remove('images')
->add('titre')
->add('description', 'textarea')
->add('prix')
->add('categories', 'choice', array(
'choices' => $this->arrayListCat,
'multiple' => true,
'mapped'=>false,
))
//->add('images', 'collection', array('type' => new ImageType()))
->add('image', 'vlabs_file', array(
'required' => false
))
;
}
/**
* #return string
*/
public function getName() {
return 'mdb_annoncebundle_annonce_sell';
}
public function getParent() {
return new AnnonceType();
}
}
And i have the following error : Catchable Fatal Error: Argument 1 passed to Vlabs\MediaBundle\EventListener\BaseFileListener::preSetData() must be an instance of Symfony\Component\Form\Event\DataEvent, instance of Symfony\Component\Form\FormEvent given in C:\wamp\www\Mdb\vendor\vlabs\media-bundle\Vlabs\MediaBundle\EventListener\BaseFileListener.php line 59
i tried to change this line :
->add('image', 'vlabs_file', array(
'required' => false
))
with :
->add('images', 'collection', array('type' => 'vlabs_file'))
but i just have the image label who appear in this case
if someone have an idea ?
I was a little bit investigating about your problem and Vlabs Media Bundle seems to be unmaintained. There is form listener on PRE_SET_DATA event (Vlabs\MediaBundle\EventListener\BaseFileListener::preSetData()) that is not compatible with new version of Symfony (it expects DataEvent as parametr instead FormEvent). They fixed it but after 1.1.1 release (you can compare dates from links). If really wanna give a try, change composer.json and run composer update. I can't guarantee there will not be another possible issues.
composer.json
"vlabs/media-bundle": "dev-master"
Library update
composer update vlabs/media-bundle

Class seems not to be a managed Doctrine entity. Did you forget to map it?

What I'm trying to do is to get an Post(Post Entity) form where I can select a featured picture from another entity(File Entity).
At the end I would like to display only the files of type "featured Image" but even if I remove my query_builder I've got a exception that says:
Class "Site\Backend\Adminbundle\Entity\File" seems not to be a managed Doctrine entity. Did you forget to map it?
Here is my PostType form
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('title')
->add('thumb', 'entity', array(
'class' => 'Site\Backend\Adminbundle\Entity\File',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('f')
//->where('f.state = :state')
//->setParameter('state', $prms['state'])
->orderBy('f.dateUpdated', 'DESC');
}
))
}
In the other hand I have my two entities:
Here is my File entity
<?php
namespace Site\Backend\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Site\Backend\AdminBundle\Entity\File
*
* #ORM\Table()
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class File {
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \DateTime
*
* #ORM\Column(name="dateCreated", type="datetime")
*/
private $dateCreated;
/**
* #var \DateTime
*
* #ORM\Column(name="dateUpdated", type="datetime")
*/
private $dateUpdated;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #Assert\File(maxSize="6000000")
*/
private $file;
/**
* #ORM\Column(type="string", length=255)
*/
public $path;
/**
* #ORM\ManyToOne(targetEntity="TypeFile", inversedBy="files")
*/
private $type;
/**
* #var string
*
* #ORM\OneToMany(targetEntity="Site\Backend\BlogBundle\Entity\Post", mappedBy="thumb")
*/
private $posts;
public function __construct() {
$this->setDateCreated(new \DateTime());
$this->setDateUpdated(new \DateTime());
$this->type = new ArrayCollection();
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function preUpload() {
$this->setDateUpdated(new \DateTime());
if (null !== $this->file) {
// do whatever you want to generate a unique name
$this->path = sha1(uniqid(mt_rand(), true)) . '.' . $this->file->guessExtension();
} else {
//throwException($e);
}
}
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload() {
if (null === $this->file) {
return;
}
// if there is an error when moving the file, an exception will
// be automatically thrown by move(). This will properly prevent
// the entity from being persisted to the database on error
$this->file->move($this->getUploadRootDir(), $this->path);
unset($this->file);
}
/**
* #ORM\PostRemove()
*/
public function removeUpload() {
if ($file = $this->getAbsolutePath()) {
if (file_exists($file)) {
unlink($file);
}
}
}
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 when displaying uploaded doc/image in the view.
return 'uploads/' . $this->type;
}
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return File
*/
public function setName($name) {
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName() {
return $this->name;
}
/**
* Set path
*
* #param string $path
* #return File
*/
public function setPath($path) {
$this->path = $path;
return $this;
}
/**
* Get path
*
* #return string
*/
public function getPath() {
return $this->path;
}
public function __toString() {
return $this->name;
}
/**
* Add type
*
* #param Site\Backend\AdminBundle\Entity\TypeFile $type
* #return File
*/
public function addType(\Site\Backend\AdminBundle\Entity\TypeFile $type) {
$this->type[] = $type;
return $this;
}
/**
* Remove type
*
* #param Site\Backend\AdminBundle\Entity\TypeFile $type
*/
public function removeType(\Site\Backend\AdminBundle\Entity\TypeFile $type) {
$this->type->removeElement($type);
}
/**
* Get type
*
* #return Doctrine\Common\Collections\Collection
*/
public function getType() {
return $this->type;
}
/**
* Set type
*
* #param Site\Backend\AdminBundle\Entity\TypeFile $type
* #return File
*/
public function setType(\Site\Backend\AdminBundle\Entity\TypeFile $type = null) {
$this->type = $type;
return $this;
}
public function getFile() {
return $this->file;
}
public function setFile($file) {
$this->file = $file;
}
/**
* Set dateCreated
*
* #param \DateTime $dateCreated
* #return File
*/
public function setDateCreated($dateCreated) {
$this->dateCreated = $dateCreated;
return $this;
}
/**
* Get dateCreated
*
* #return \DateTime
*/
public function getDateCreated() {
return $this->dateCreated;
}
/**
* Set dateUpdated
*
* #param \DateTime $dateUpdated
* #return File
*/
public function setDateUpdated($dateUpdated) {
$this->dateUpdated = $dateUpdated;
return $this;
}
/**
* Get dateUpdated
*
* #return \DateTime
*/
public function getDateUpdated() {
return $this->dateUpdated;
}
/**
* Add posts
*
* #param \Site\Backend\BlogBundle\Entity\Post $posts
* #return File
*/
public function addPost(\Site\Backend\BlogBundle\Entity\Post $posts)
{
$this->posts[] = $posts;
return $this;
}
/**
* Remove posts
*
* #param \Site\Backend\BlogBundle\Entity\Post $posts
*/
public function removePost(\Site\Backend\BlogBundle\Entity\Post $posts)
{
$this->posts->removeElement($posts);
}
/**
* Get posts
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getPosts()
{
return $this->posts;
}
}
And Here is my Post entity
<?php
namespace Site\Backend\BlogBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Post
*
* #ORM\Table()
* #ORM\Entity
*/
class Post
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var \DateTime
*
* #ORM\Column(name="dateCreated", type="datetime")
*/
private $dateCreated;
/**
* #var \DateTime
*
* #ORM\Column(name="dateUpdated", type="datetime")
*/
private $dateUpdated;
/**
* #var \DateTime
*
* #ORM\Column(name="datePublished", type="datetime", nullable=true)
*/
private $datePublished;
/**
* #var string
*
* #ORM\Column(name="state", type="string", length=255)
*/
private $state;
/**
* #var string
*
* #ORM\Column(name="content", type="text")
*/
private $content;
/**
* #var Author
* #ORM\ManyToOne(targetEntity="Site\Backend\AdminBundle\Entity\User", inversedBy="posts")
*/
private $author;
/**
* #var Thumb
* #ORM\ManyToOne(targetEntity="Site\Backend\AdminBundle\Entity\File", inversedBy="posts")
*/
private $thumb;
/**
* #var Comments
* #ORM\OneToMany(targetEntity="Comment", mappedBy="post")
*/
private $comments;
/**
* #var Categories
* #ORM\ManyToMany(targetEntity="Category", cascade={"persist"})
*/
private $categories;
/**
* #var Tags
* #ORM\ManyToMany(targetEntity="Tag", cascade={"persist"})
*/
private $tags;
/**
* Constructeur
*/
public function __construct()
{
$this->setDateCreated(new \DateTime());
$this->setDateUpdated(new \DateTime());
$this->comments = new ArrayCollection();
$this->Categories = new ArrayCollection();
$this->tags = new ArrayCollection();
}
public function __toString(){
return $this->title;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
* #return Post
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set dateCreated
*
* #param \DateTime $dateCreated
* #return Comment
*/
public function setDateCreated($dateCreated)
{
$this->dateCreated = $dateCreated;
return $this;
}
/**
* Get dateCreated
*
* #return \DateTime
*/
public function getDateCreated()
{
return $this->dateCreated;
}
/**
* Set dateUpdated
*
* #param \DateTime $dateUpdated
* #return Comment
*/
public function setDateUpdated($dateUpdated)
{
$this->dateUpdated = $dateUpdated;
return $this;
}
/**
* Get dateUpdated
*
* #return \DateTime
*/
public function getDateUpdated()
{
return $this->dateUpdated;
}
/**
* Get datePublished
*
* #return \DateTime
*/
public function getDatePublished()
{
return $this->datePublished;
}
/**
* Set datePublished
*
* #param \DateTime $datePublished
* #return Comment
*/
public function setDatePublished($datePublished)
{
$this->datePublished = $datePublished;
return $this;
}
/**
* Set state
*
* #param string $state
* #return Post
*/
public function setState($state)
{
$this->state = $state;
return $this;
}
/**
* Get state
*
* #return string
*/
public function getState()
{
return $this->state;
}
/**
* Set content
*
* #param string $content
* #return Post
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content
*
* #return string
*/
public function getContent()
{
return $this->content;
}
/**
* Set author
*
* #param \Site\Backend\AdminBundle\Entity\User $author
* #return Post
*/
public function setAuthor(\Site\Backend\AdminBundle\Entity\User $author = null)
{
$this->author = $author;
return $this;
}
/**
* Get author
*
* #return \Site\Backend\AdminBundle\Entity\User
*/
public function getAuthor()
{
return $this->author;
}
/**
* Add comments
*
* #param \Site\Backend\BlogBundle\Entity\Comment $comments
* #return Post
*/
public function addComment(\Site\Backend\BlogBundle\Entity\Comment $comments)
{
$this->comments[] = $comments;
return $this;
}
/**
* Remove comments
*
* #param \Site\Backend\BlogBundle\Entity\Comment $comments
*/
public function removeComment(\Site\Backend\BlogBundle\Entity\Comment $comments)
{
$this->comments->removeElement($comments);
}
/**
* Get comments
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getComments()
{
return $this->comments;
}
/**
* Add Categories
*
* #param \Site\Backend\BlogBundle\Entity\Category $categories
* #return Post
*/
public function addCategory(\Site\Backend\BlogBundle\Entity\Category $category)
{
$this->categories[] = $category;
return $this;
}
/**
* Add Categories
*
* #param \Site\Backend\BlogBundle\Entity\Category $categories
* #return Post
*/
public function addCategoriesNew(\Site\Backend\BlogBundle\Entity\Category $category)
{
$this->categories[] = $category;
return $this;
}
/**
* Remove Categories
*
* #param \Site\Backend\BlogBundle\Entity\Category $categories
*/
public function removeCategory(\Site\Backend\BlogBundle\Entity\Category $category)
{
$this->categories->removeElement($category);
}
/**
* Remove Categories
*
* #param \Site\Backend\BlogBundle\Entity\Category $categories
*/
public function removeCategoriesNew(\Site\Backend\BlogBundle\Entity\Category $category)
{
}
/**
* Get Categories
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCategories()
{
return $this->categories;
}
/**
* Get Categories
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCategoriesNew()
{
//return $this->categories;
}
/**
* Add tags
*
* #param \Site\Backend\BlogBundle\Entity\tag $tags
* #return Post
*/
public function addTag(\Site\Backend\BlogBundle\Entity\Tag $tags)
{
$this->tags[] = $tags;
return $this;
}
/**
* Add tags
*
* #param \Site\Backend\BlogBundle\Entity\tag $tags
* #return Post
*/
public function addTagsNew(\Site\Backend\BlogBundle\Entity\Tag $tags)
{
$this->tags[] = $tags;
return $this;
}
/**
* Remove tags
*
* #param \Site\Backend\BlogBundle\Entity\Tag $tags
*/
public function removeTag(\Site\Backend\BlogBundle\Entity\Tag $tags)
{
$this->tags->removeElement($tags);
}
/**
* Remove Tags
*
* #param \Site\Backend\BlogBundle\Entity\tag $tags
*/
public function removeTagsNew(\Site\Backend\BlogBundle\Entity\Tag $tags)
{
//$this->tags->removeElement($tags);
}
/**
* Get Tags
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getTags()
{
return $this->tags;
}
/**
* Get Tags
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getTagsNew()
{
//return $this->Tags;
}
/**
* Add Categories
*
* #param \Site\Backend\BlogBundle\Entity\Category $categories
* #return Post
*/
public function addCategorie(\Site\Backend\BlogBundle\Entity\Category $categories)
{
$this->categories[] = $categories;
return $this;
}
/**
* Remove Categories
*
* #param \Site\Backend\BlogBundle\Entity\Category $categories
*/
public function removeCategorie(\Site\Backend\BlogBundle\Entity\Category $categories)
{
$this->categories->removeElement($categories);
}
/**
* #ORM\preUpdate
*/
public function setUpdateValue(){
$this->setDateUpdated(new \DateTime());
}
/**
* Set thumb
*
* #param \Site\Backend\AdminBundle\Entity\File $thumb
* #return Post
*/
public function setThumb(\Site\Backend\AdminBundle\Entity\File $thumb = null)
{
$this->thumb = $thumb;
return $this;
}
/**
* Get thumb
*
* #return \Site\Backend\AdminBundle\Entity\File
*/
public function getThumb()
{
return $this->thumb;
}
}
Thanks in advance
I hope I was clear, if It is not the case please tell me.
Try changing:
Site\Backend\Adminbundle\Entity\File
to
Site\Backend\AdminBundle\Entity\File
An other way to resolve the case :
->add('thumb', null, array(
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('f')
->select('f')
->leftJoin('f.type', 't')
->where('t.name = :type')
->setParameter('type', 'Featured Images')
->orderBy('f.dateUpdated', 'DESC');
}
))
In case you are working with multiple connections, you might have forgotten to map your bundle. Make sure it's the case in app/config/config.yml:
orm:
entity_managers:
default:
mappings:
AppBundle: ~
SiteBackendAdminBundle: ~
Or if you want to split in several entity managers:
orm:
entity_managers:
default:
mappings:
AppBundle: ~
admin:
mappings:
SiteBackendAdminBundle: ~
Documentation Symfony/Doctrine: Multiple Entity Managers.

How do i solve Semantical error: "Class has no association named.."

i am following part 5 of the symblog symfony2 tutorial:
http://tutorial.symblog.co.uk/docs/customising-the-view-more-with-twig.html
under heading: The Homepage - Blogs and Comments
when i get to update:
// src/Blogger/BlogBundle/Repository/BlogRepositoy.php
public function getLatestBlogs($limit = null)
{
$qb = $this->createQueryBuilder('b')
->select('b, c')
->leftJoin('b.comments', 'c')
->addOrderBy('b.created', 'DESC');
if (false === is_null($limit))
$qb->setMaxResults($limit);
return $qb->getQuery()
->getResult();
}
and also when i update:
{# src/Blogger/BlogBundle/Resources/views/Page/index.html.twig #}
{# .. #}
<footer class="meta">
<p>Comments: {{ blog.comments|length }}</p>
<p>Posted by <span class="highlight">{{ blog.author }}</span> at {{ blog.created|date('h:iA') }}</p>
<p>Tags: <span class="highlight">{{ blog.tags }}</span></p>
</footer>
{# .. #}
i then refresh my browser and get error:
[Semantical Error] line 0, col 71 near 'c ORDER BY b.created': Error: Class
Blogger\BlogBundle\Entity\Blog has no association named comments
500 Internal Server Error - QueryException
<?php
// src/Blogger/BlogBundle/Entity/Blog.php
namespace Blogger\BlogBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity(repositoryClass="Blogger\BlogBundle\Repository\BlogRepository")
* #ORM\Table(name="blog")
* #ORM\HasLifecycleCallbacks()
*/
class Blog
{
public function __toString()
{
return $this->getTitle();
}
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string")
*/
protected $title;
/**
* #ORM\Column(type="string", length=100)
*/
protected $author;
/**
* #ORM\Column(type="text")
*/
protected $blog;
/**
* #ORM\Column(type="string", length="20")
*/
protected $image;
/**
* #ORM\Column(type="text")
*/
protected $tags;
protected $comments;
/**
* #ORM\Column(type="datetime")
*/
protected $created;
/**
* #ORM\Column(type="datetime")
*/
protected $updated;
public function __construct()
{
$this->comments = new ArrayCollection();
$this->setCreated(new \DateTime());
$this->setUpdated(new \DateTime());
}
public function setUpdatedValue()
{
$this->setUpdated(new \DateTime());
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set author
*
* #param string $author
*/
public function setAuthor($author)
{
$this->author = $author;
}
/**
* Get author
*
* #return string
*/
public function getAuthor()
{
return $this->author;
}
/**
* Set blog
*
* #param text $blog
*/
public function setBlog($blog)
{
$this->blog = $blog;
}
/**
* Get blog
*
* #return text
*/
public function getBlog($length = null)
{
if (false === is_null($length) && $length > 0)
return substr($this->blog, 0, $length);
else
return $this->blog;
}
/**
* Set image
*
* #param string $image
*/
public function setImage($image)
{
$this->image = $image;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
/**
* Set tags
*
* #param text $tags
*/
public function setTags($tags)
{
$this->tags = $tags;
}
/**
* Get tags
*
* #return text
*/
public function getTags()
{
return $this->tags;
}
/**
* Set created
*
* #param datetime $created
*/
public function setCreated($created)
{
$this->created = $created;
}
/**
* Get created
*
* #return datetime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated
*
* #param datetime $updated
*/
public function setUpdated($updated)
{
$this->updated = $updated;
}
/**
* Get updated
*
* #return datetime
*/
public function getUpdated()
{
return $this->updated;
}
}
please help solve this. i dont know where i went wrong
thanks
You didn't paste the src/Blogger/BlogBundle/Entity/Blog.php file. It would help resolving your issue.
Most probably you didn't add comments field to your entity (or didn't annotate it properly).
Similar problem: Doctrine2: What is wrong with the association between these entities?
EDIT: Now when you pasted your entity I can see the comments field is not annotated. Doctrine's entity manager doesn't know anything about it. You have to provide mapping (in your case via annotations).
EDIT 2:
In your entity you should have (src/Blogger/BlogBundle/Entity/Blog.php):
/**
* #ORM\OneToMany(targetEntity="Comment", mappedBy="blog")
*/
protected $comments;
but you have:
protected $comments;
Mapping is missing. Doctrine doesn't know how to use your field.
I have also followed the symblog tutorial. My blog.php file is as follows:
<?php
namespace Blogger\BlogBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Blogger\BlogBundle\Entity\Blog
*/
class Blog
{
/**
* #var integer $id
*/
private $id;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #var string $title
*/
private $title;
/**
* #var string $author
*/
private $author;
/**
* #var string $blog
*/
private $blog;
/**
* #var string $image
*/
private $image;
/**
* #var string $tags
*/
private $tags;
/**
* #var string $comment
*/
private $comment;
/**
* #var datetime $created
*/
private $created;
/**
* #var datetime $updated
*/
private $updated;
public function __construct()
{
$this->comments = new ArrayCollection();
$this->setCreated(new \DateTime());
$this->setUpdated(new \DateTime());
}
/**
* Set title
*
* #param string $title
*/
public function setTitle($title)
{
$this->title = $title;
$this->setSlug($this->title);
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set author
*
* #param string $author
*/
public function setAuthor($author)
{
$this->author = $author;
}
/**
* Get author
*
* #return string
*/
public function getAuthor()
{
return $this->author;
}
/**
* Set blog
*
* #param string $blog
*/
public function setBlog($blog)
{
$this->blog = $blog;
}
/**
* Get blog
*
* #return string
*/
public function getBlog($length = null)
{
if (false === is_null($length) && $length > 0)
return substr($this->blog, 0, $length);
else
return $this->blog;
}
/**
* Set image
*
* #param string $image
*/
public function setImage($image)
{
$this->image = $image;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
/**
* Set tags
*
* #param string $tags
*/
public function setTags($tags)
{
$this->tags = $tags;
}
/**
* Get tags
*
* #return string
*/
public function getTags()
{
return $this->tags;
}
/**
* Set comment
*
* #param string $comment
*/
public function setComment($comment)
{
$this->comment = $comment;
}
/**
* Get comment
*
* #return string
*/
public function getComment()
{
return $this->comment;
}
/**
* Set created
*
* #param datetime $created
*/
public function setCreated($created)
{
$this->created = $created;
}
/**
* Get created
*
* #return datetime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated
*
* #param datetime $updated
*/
public function setUpdated($updated)
{
$this->updated = $updated;
}
/**
* Get updated
*
* #return datetime
*/
public function getUpdated()
{
return $this->updated;
}
public function addComment(Comment $comment)
{
$this->comments[] = $comment;
}
public function getComments()
{
return $this->comments;
}
/**
* #ORM\preUpdate
*/
public function setUpdatedValue()
{
$this->setUpdated(new \DateTime());
}
/**
* #var Blogger\BlogBundle\Entity\Comment
*/
private $comments;
public function __toString()
{
return $this->getTitle();
}
/**
* #var string $slug
*/
protected $slug;
/**
* Set slug
*
* #param string $slug
*/
public function setSlug($slug)
{
$this->slug = $this->slugify($slug);
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
public function slugify($text)
{
$text = preg_replace('#[^\\pL\d]+#u', '-', $text);
$text = trim($text, '-');
if (function_exists('iconv'))
{
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
}
$text = strtolower($text);
$text = preg_replace('#[^-\w]+#', '', $text);
if (empty($text))
{
return 'n-a';
}
return $text;
} }
Hope this helps you.
Your code is missing
/**
* #var Blogger\BlogBundle\Entity\Comment
*/
private $comments;

Categories