I'm using Symfony 2.7.39 and FOSRestBundle to build a simple REST api.
In this case I have this entity:
class DocumentacionMaquina extends Documentacion
{
/**
* #ORM\ManyToOne(targetEntity="PDCA\RestBundle\Entity\Archivo", cascade={"all"})
* #ORM\JoinColumn(name="declaracion_conformidad_id", referencedColumnName="id", nullable=true, onDelete="CASCADE")
*
* #Serializer\Groups({"details"})
*/
private $declaracion_conformidad;
// ...
}
ArchivoType:
class ArchivoType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('nombre');
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'PDCA\RestBundle\Entity\Archivo',
'csrf_protection' => false,
'cascade_validation' => true
));
}
}
DocumentacionMaquinaType:
class DocumentacionMaquinaType extends DocumentacionType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->add('maquina', 'entity', array(
'class' => 'PDCA\RestBundle\Entity\Maquina'
))
->add('declaracion_conformidad', new ArchivoType(),
array('required'=>false)
)
;
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'PDCA\RestBundle\Entity\DocumentacionMaquina',
'csrf_protection' => false,
'cascade_validation' => true
));
}
}
When I create a new DocumentacionMaquina entity launching a POST it works as expected:
{
"pdca_restbundle_documentacion":
{
"maquina": 752,
"declaracion_conformidad": {
"nombre": "fichero10"
}
}
But I would like to send a null (edit entity and create new entities with optional Archivo):
{
"pdca_restbundle_documentacion":
{
"maquina": 752,
"declaracion_conformidad": null
}
This is the validation error when I send a null value:
This value is not valid.
In my controller:
$entity = new DocumentacionMaquina();
$form = $this->createForm(new DocumentacionMaquinaType(), $entity, array('method' => $request->getMethod()));
$form->submit($request->get($form->getName()), false);
if !($form->isValid()) {
return $this->view(array('form' => $form), Codes::HTTP_BAD_REQUEST);
}
Any help will be appreciated.
EDIT #1
I created a simple entities with no inheritance for test but with equal result.
Entity Prueba:
namespace PDCA\RestBundle\Entity;
use Doctrine\ORM\Mapping AS ORM;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
*/
class Prueba
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*
* #Serializer\Groups({"list", "details"})
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="PDCA\RestBundle\Entity\Hijo", cascade={"all"})
* #ORM\JoinColumn(name="marcado_ce_id", referencedColumnName="id", nullable=true, onDelete="CASCADE")
*
* #Serializer\Groups({"list", "details"})
*/
private $marcado_ce;
/**
* #ORM\Column(type="string", unique=false, length=255, nullable=false)
*
* #Serializer\Groups({"list", "details"})
*
* #Assert\NotBlank()
* #Assert\Length(max=255)
*/
private $nombre;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set marcado_ce
*
* #param \DateTime $marcado_ce
* #return Prueba
*/
public function setMarcadoCe(Hijo $marcado_ce = null)
{
$this->marcado_ce = $marcado_ce;
return $this;
}
/**
* Get marcado_ce
*
* #return \DateTime
*/
public function getMarcadoCe()
{
return $this->marcado_ce;
}
/**
* Set nombre
*
* #param string $nombre
* #return Prueba
*/
public function setNombre($nombre)
{
$this->nombre = $nombre;
return $this;
}
/**
* Get nombre
*
* #return string
*/
public function getNombre()
{
return $this->nombre;
}
}
Entity Hijo
namespace PDCA\RestBundle\Entity;
use Doctrine\ORM\Mapping AS ORM;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
*
*/
class Hijo
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*
* #Serializer\Groups({"list", "details", "backend_creacion"})
*/
private $id;
/**
* #ORM\Column(type="string", unique=false, length=255, nullable=false)
*
* #Serializer\Groups({"list", "details"})
*
* #Assert\NotBlank()
* #Assert\Length(max=255)
*/
private $nombre;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set nombre
*
* #param string $nombre
* #return Artchivo
*/
public function setNombre($nombre)
{
$this->nombre = $nombre;
return $this;
}
/**
* Get nombre
*
* #return string
*/
public function getNombre()
{
return $this->nombre;
}
}
PruebaType and HijoType:
namespace PDCA\RestBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use PDCA\RestBundle\Entity\Prueba;
class PruebaType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('nombre')
->add('marcado_ce', new HijoType(), array('required'=>false))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver) {
/** #var OptionResolver $resolver */
$this->configureOptions($resolver);
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'PDCA\RestBundle\Entity\Prueba',
'csrf_protection' => false
));
}
/**
* #return string
*/
public function getName()
{
return 'pdca_restbundle_prueba';
}
}
Type Hijo
namespace PDCA\RestBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class HijoType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('nombre')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver) {
/** #var OptionResolver $resolver */
$this->configureOptions($resolver);
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'PDCA\RestBundle\Entity\Hijo',
'csrf_protection' => false
));
}
/**
* #return string
*/
public function getName()
{
return null;
}
}
Controller:
$entity = new Prueba();
$form = $this->createForm(new PruebaType(), $entity, array('method' => $request->getMethod()));
$form->submit($request->get($form->getName()), false);
if ($form->isValid()) {
//Persist $entity
}
return $this->view(array('form' => $form), Codes::HTTP_BAD_REQUEST);
When I do a POST with subentity, entities Prueba and Hija are persisted sucesfully:
{
"pdca_restbundle_prueba": {
"nombre": "nombre prueba",
"marcado_ce":
{
"nombre": "fichero4"
}
}
}
But when I use "marcado_ce": null:
{
"pdca_restbundle_prueba": {
"nombre": "nombre prueba2",
"marcado_ce": null
}
}
This fail with this message:
{
"code": 400,
"message": "Validation Failed",
"errors": {
"errors": [
"Este valor no es valido."
],
"children": {
"nombre": {},
"marcado_ce": {
"children": {
"nombre": {}
}
}
}
}
}
Debugging this problem, here is where code launch an exception resulting in validation failed:
File Form.php, line 570:
if ($this->config->getCompound()) {
if (null === $submittedData) {
$submittedData = array();
}
if (!is_array($submittedData)) {
**throw new TransformationFailedException('Compound forms expect an array or NULL on submission.');**
}
I uploaded a image with stack trace here:
https://i.stack.imgur.com/QzPDc.png
I edited Form.php code replacing Exception code with this (line 750). But this isn't a solution. I will try to understand what is the root cause, maybe I miss something with symfony-forms.
if (!is_array($submittedData)) {
$submittedData = array();
}
Related
I am trying to upload a file with symfony. But I have an error when I send data formulaire to controller. Variable file is null and function move file don't working.
code entity (par uplaod):
<?php
namespace AppBundle\Entity;
use AppBundle\Model\CompanyInterface;
use AppBundle\Model\RecruiterInterface;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Company.
*
* #ORM\Table(name="company")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CompanyRepository")
*/
class Company implements CompanyInterface
{
/**
* #var string
*
* #ORM\Column(name="id", type="guid")
* #ORM\Id
* #ORM\GeneratedValue(strategy="UUID")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, unique=true)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="description", type="text")
*/
private $description;
/**
* #var array
*
* #ORM\Column(name="activities", type="array")
*/
private $activities;
/**
* #var RecruiterInterface
*
* #ORM\OneToOne(targetEntity="AppBundle\Entity\Recruiter", cascade={"persist"})
*/
private $recruiter;
/**
* #var string
*
* #ORM\Column(name="path", type="string", length=255,nullable=true)
*/
private $logo;
/**
* #Assert\File(maxSize="6000000")
*/
private $file;
/**
* {#inheritdoc}
*/
public static function create(string $name, RecruiterInterface $recruiter, string $description = '', array $activities = []): CompanyInterface
{
return new self($name, $recruiter, $description, $activities);
}
/**
* {#inheritdoc}
*/
public function update(string $name, string $description, array $activities): CompanyInterface
{
$this->name = $name;
$this->description = $description;
$this->activities = $activities;
return $this;
}
/**
* {#inheritdoc}
*/
public function updateName(string $name): CompanyInterface
{
$this->name = $name;
return $this;
}
/**
* {#inheritdoc}
*/
public function getId(): string
{
return $this->id;
}
/**
* {#inheritdoc}
*/
public function getName(): ?string
{
return $this->name;
}
/**
* function setName.
*
* #param string $name
*
* #return string
*/
public function setName(string $name)
{
$this->name = $name;
return $this;
}
/**
* function setDescription.
*
* #param string $description
*
* #return string
*/
public function setDescription(string $description)
{
$this->description = $description;
return $this;
}
/**
* function setActivities.
*
* #param string $activities
*
* #return string
*/
public function setActivities(string $activities)
{
$this->activities = $activities;
return $this;
}
/**
* {#inheritdoc}
*/
public function getDescription(): ?string
{
return $this->description;
}
/**
* {#inheritdoc}
*/
public function getActivities()
{
return $this->activities;
}
/**
* {#inheritdoc}
*/
public function getRecruiter(): ?RecruiterInterface
{
return $this->recruiter;
}
/**
* #return string
*/
public function __toString()
{
return $this->name;
}
/**
* {#inheritdoc}
*/
public function updateLogo(string $logo): CompanyInterface
{
$this->logo = $logo;
return $this;
}
/**
* Get file.
*
* #return UploadedFile
*/
public function getFile()
{
return $this->file;
}
/**
* Sets file.
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
}
/**
* Set logo.
*
* #param string $logo
*
* #return Company
*/
public function setLogo($logo)
{
$this->logo = $logo;
return $this;
}
/**
* Get logo.
*
* #return string
*/
public function getLogo()
{
return $this->logo;
}
/**
* function upload.
*/
public function upload()
{
// the file property can be empty if the field is not required
if (null === $this->getFile()) {
return;
}
$this->file->move($this->getUploadRootDir(),$this->path);
// set the path property to the filename where you've saved the file
$this->logo = $this->getFile()->getClientOriginalName();
// clean up the file property as you won't need it anymore
//$this->file = null;
}
/**
* function getUploadRootDir.
*/
protected function getUploadRootDir()
{
return __DIR__.'/../../../web/uploads';
}
}
code formType(content variable file):
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
/**
* Class CompanyType.
*/
class CompanyType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('description')
->add('activities', TextType::class)
->add('file', FileType::class)
;
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Company',
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return '';
}
}
code other FormTyp(I use form imbrique):
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use AppBundle\Entity\Recruiter;
/**
* Class RecruiterType.
*/
class RecruiterType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->remove('username');
$builder->remove('plainPassword');
$builder
->add('email')
->add('lastname')
->add('firstname')
->add('phone')
->add('civility', ChoiceType::class, array(
'choices' => ['Mr' => 'Mr', 'Mrs' => 'Mrs'], 'expanded' => true, 'multiple' => false,
))
->add('company', CompanyType::class)
;
}
/**
* function get Parent Form.
*
* #return string
*/
public function getParent()
{
return 'FOS\UserBundle\Form\Type\RegistrationFormType';
}
/**
* name for this form.
*
* #return string
*/
public function getBlockPrefix()
{
return '';
}
/**
* name for this form.
*
* #return string
*/
public function getName()
{
return $this->getBlockPrefix();
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Recruiter::class,
'allow_extra_fields' => true,
'csrf_protection' => false,
));
}
}
function post (persist object):
public function post(array $parameters, bool $submitted = true, array $options = [])
{
/** #var Recruiter $recruiter */
$recruiter = $this->formHandler->handle(
$this->userManager->createRecruiter(),
$parameters,
Request::METHOD_POST,
$submitted,
$options
);
if (false === $submitted) {
return $recruiter;
}
$recruiter->submit($parameters);
if ($recruiter->isSubmitted() && $recruiter->isValid()) {
$recruiter->getData()->setCompany($recruiter->getData()->getCompany());
$recruiter->getData()->getCompany()->upload();
$this->em->persist($recruiter->getData());
$this->em->flush();
$event = new FormEvent($recruiter, $this->request);
$this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
return $recruiter->getData();
}
return $recruiter;
}
code controller :
<?php
namespace AppBundle\Controller\Recruiter;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
use FOS\UserBundle\Event\GetResponseUserEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use AppBundle\Handler\RecruiterHandler;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use AppBundle\Entity\Recruiter;
use Symfony\Component\HttpFoundation\RedirectResponse;
use AppBundle\Util\UserManagerr;
/**
* Class RegistrationRecruiterController.
*/
class RegistrationRecruiterController extends BaseController
{
/**
* #Template()
* #Route("/register", name="register_recruiter")
*
* #param Request $request
*
* #return array|\Symfony\Component\HttpFoundation\RedirectResponse
*/
public function registerAction(Request $request)
{
try {
$user = new UserManagerr();
$dispatcher = $this->get('event_dispatcher');
$user = $user->createRecruiter();
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$recruiter = $this->getHandler()->post($request->request->all(), $request->isMethod(Request::METHOD_POST));
if ($recruiter instanceof Recruiter) {
$url = $this->generateUrl('fos_user_registration_check_email');
$response = new RedirectResponse($url);
return $response;
}
} catch (InvalidFormException $e) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event);
return [
'form' => $e->getForm()->createView(),
'edit' => false,
'event' => $event->getResponse(),
];
}
return ['form' => $recruiter->createView()];
}
/**
* #return RecruiterHandler
*/
public function getHandler()
{
return $this->get(RecruiterHandler::class);
}
}
I use form imbriqu (form in other form) but when I send form I have all variable from object but variable file has null and function move doesn't work.
How to resolve this error please?
Thanks in advance for any help.
Change this
public function post(array $parameters, bool $submitted = true, array $options = [])
For
public function post(Request $request, bool $submitted = true, array $options = [])
[...]
$recruiter->submit($request);
[...]
Your issue is probably in the for tag, which you should declare it like:
{{ form_start(form, {'method': 'post', 'action': '', 'attr': {'class': '', 'novalidate': 'novalidate' }}) }}
I don't find solutions for several days to resolve my issue. I want to upload multiple images when I create a Post. My Post entity has a OneToMany relation with Image Entity. I use an embedded form in my PostType. It is a CollectionType of ImageType::class. To manage my upload functionality, I wrote an event listener called ImageUploadListener which injects my custom service called FileUploader.
This listener call a uploadFile function when a preUpdate and a prePersist event is handled. This function call my upload function from my FileUploader to move the image/file... to a target directory and to return a filename.
After that, I try to instantiate an Image Entity and to set the appropriate datas. But it doesn't work, only a file seems to be stored properly but with an additional entry unwanted in my db. (In my Image Table, for one image uploaded, I've got an entry with id 1 for example, a post_id set to NULL and file field set to /tmp/random number).
Please, could you help me ?
Post Entity
namespace UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Post
*
* #ORM\Table(name="post")
* #ORM\Entity(repositoryClass="UserBundle\Repository\PostRepository")
*/
class Post
{
/**
* #var int
*
* #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 string
*
* #ORM\Column(name="Content", type="text")
*/
private $content;
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="posts")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
/**
* #ORM\OneToMany(targetEntity="Image", mappedBy="post", cascade={"persist", "remove"})
*/
private $images;
/**
* Get id
*
* #return int
*/
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 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 post
*
* #param \
*
* #return Post
*/
public function setUser($user)
{
$this->user = $user;
return $this;
}
/**
* Get post
*
* #return \?
*/
public function getUser()
{
return $this->user;
}
/**
* Constructor
*/
public function __construct()
{
$this->images = new ArrayCollection();
}
/**
* Add image
*
* #param \UserBundle\Entity\Image $image
*
* #return Post
*/
public function addImage(\UserBundle\Entity\Image $image)
{
$this->images[] = $image;
return $this;
}
/**
* Remove image
*
* #param \UserBundle\Entity\Image $image
*/
public function removeImage(\UserBundle\Entity\Image $image)
{
$this->images->removeElement($image);
}
/**
* Get images
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getImages()
{
return $this->images;
}
}
Image Entity
namespace UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity(repositoryClass="UserBundle\Entity\ImageRepository")
*/
class Image
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $file;
public function setFile($file)
{
$this->file = $file;
return $this;
}
public function getFile()
{
return $this->file;
}
/**
* #ORM\ManyToOne(targetEntity="Post", inversedBy="images")
* #ORM\JoinColumn(name="post_id", referencedColumnName="id")
*/
private $post;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set post
*
* #param \UserBundle\Entity\Post $post
*
* #return Image
*/
public function setPost(\UserBundle\Entity\Post $post = null)
{
$this->post = $post;
return $this;
}
/**
* Get post
*
* #return \UserBundle\Entity\Post
*/
public function getPost()
{
return $this->post;
}
}
PostType
namespace UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
//use Ivory\CKEditorBundle\Form\Type\CKEditorType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use UserBundle\Entity\Post;
class PostType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('content')
->add('images', CollectionType::class, array (
'entry_type' => ImageType::class,
'entry_options' => array('label' => false),
'allow_add' => true,
'allow_delete' => true
))
;
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
//'data_class' => 'UserBundle\Entity\Post',
'data_class' => Post::class,
//'csrf_protection' => false
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'userbundle_post';
}
}
ImageType
namespace UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use UserBundle\Entity\Image;
class ImageType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('file', FileType::class, [
'required' => false,
'data_class' => null,
])
;
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Image::class,
//'csrf_protection' => false
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'userbundle_image';
}
}
EDIT: ImageUploadListener
//src/UserBundle/EventListener/ImageUploadListener.php
namespace UserBundle\EventListener;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\File\File;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use UserBundle\Entity\User;
use UserBundle\Entity\Post;
use UserBundle\Entity\Image;
use UserBundle\Service\FileUploader;
class ImageUploadListener
{
private $uploader;
public function __construct(FileUploader $uploader)
{
$this->uploader = $uploader;
}
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
$this->uploadFile($entity);
}
public function preUpdate(PreUpdateEventArgs $args)
{
$entity = $args->getEntity();
$this->uploadFile($entity);
}
private function uploadFile($entity)
{
if ($entity instanceof Post) {
$post = $entity;
$images = $post->getImages();
foreach ($images as $image) {
if ($image->getFile() instanceof UploadedFile) {
$imageName = $this->uploader->upload($image->getFile());
// to avoid persisting FileObject in DB
$post->removeImage($image);
$postImage = new Image();
$postImage->setFile($imageName);
$postImage->setPost($post);
$post->addImage($postImage);
}
}
}
return;
}
}
FileUploader
namespace UserBundle\Service;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class FileUploader
{
private $targetDir;
public function __construct($targetDir)
{
$this->targetDir = $targetDir;
}
public function upload(UploadedFile $file)
{
$fileName = md5(uniqid()).'.'.$file->guessExtension();
$file->move($this->getTargetDir(), $fileName);
return $fileName;
}
public function getTargetDir()
{
return $this->targetDir;
}
}
I have this problem when i execute my project, I use FormEvent in FormType
entity Departement.php:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Departement
*
* #ORM\Table(name="departement")
* #ORM\Entity(repositoryClass="AppBundle\Repository\DepartementRepository")
*/
class Departement
{
/**
* #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)
*/
private $name;
/**
* #var int
*
* #ORM\Column(name="code", type="integer")
*/
private $code;
/**
*#ORM\ManyToOne(targetEntity="AppBundle\Entity\Region")
*/
private $region;
/**
*#ORM\OneToMany(targetEntity="AppBundle\Entity\Ville", mappedBy="departement")
*/
private $villes;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Departement
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set code
*
* #param integer $code
* #return Departement
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* Get code
*
* #return integer
*/
public function getCode()
{
return $this->code;
}
/**
* Constructor
*/
public function __construct()
{
$this->villes = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Set region
*
* #param \AppBundle\Entity\Region $region
* #return Departement
*/
public function setRegion(\AppBundle\Entity\Region $region = null)
{
$this->region = $region;
return $this;
}
/**
* Get region
*
* #return \AppBundle\Entity\Region
*/
public function getRegion()
{
return $this->region;
}
/**
* Add villes
*
* #param \AppBundle\Entity\Ville $villes
* #return Departement
*/
public function addVille(\AppBundle\Entity\Ville $villes)
{
$this->villes[] = $villes;
return $this;
}
/**
* Remove villes
*
* #param \AppBundle\Entity\Ville $villes
*/
public function removeVille(\AppBundle\Entity\Ville $villes)
{
$this->villes->removeElement($villes);
}
/**
* Get villes
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getVilles()
{
return $this->villes;
}
public function __toString(){
return $this->name;
}
}
entity ville.php:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Ville
*
* #ORM\Table(name="ville")
* #ORM\Entity(repositoryClass="AppBundle\Repository\VilleRepository")
*/
class Ville
{
/**
* #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)
*/
private $name;
/**
* #var int
*
* #ORM\Column(name="code", type="integer")
*/
private $code;
/**
*#ORM\ManyToOne(targetEntity="AppBundle\Entity\Departement")
*/
private $departement;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Ville
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set code
*
* #param integer $code
* #return Ville
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* Get code
*
* #return integer
*/
public function getCode()
{
return $this->code;
}
/**
* Set departement
*
* #param \AppBundle\Entity\Departement $departement
* #return Ville
*/
public function setDepartement(\AppBundle\Entity\Departement $departement = null)
{
$this->departement = $departement;
return $this;
}
/**
* Get departement
*
* #return \AppBundle\Entity\Departement
*/
public function getDepartement()
{
return $this->departement;
}
public function __toString(){
return $this->name;
}
}
Form MedecinType.php:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormInterface;
use AppBundle\Entity\Region;
use AppBundle\Entity\Departement;
use AppBundle\Entity\Ville;
class MedecinType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('region', EntityType::class, [
'class' => 'AppBundle\Entity\Region',
'placeholder' => 'Sélectionnez votre région',
'mapped' => false,
'required' => false
]);
$builder->get('region')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) {
$form = $event->getForm();
$this->addDepartementField($form->getParent(), $form->getData());
}
);
}
private function addDepartementField(FormInterface $form, Region $region)
{
$builder = $form->getConfig()->getFormFactory()->createNamedBuilder(
'departement',
EntityType::class,
null,
[
'class' => 'AppBundle\Entity\Departement',
'placeholder' => 'Sélectionnez votre département',
'mapped' => false,
'required' => false,
'auto_initialize' => false,
'choices' => $region->getDepartements()
]);
$builder->addEventListener(
FormEvents::POST_SUBMIT,
function(FormEvent $event) {
$form= $event->getForm();
$this->addVilleField($form->getParent(), $form->getData());
}
);
$form->add($builder->getForm());
}
private function addVilleField(FormInterface $form, Departement $departement)
{
$form->add('ville', EntityType::class, [
'class' => 'AppBundle\Entity\Ville',
'placeholder' => 'Sélectionnez votre ville',
'choices' => $departement->getVilles()
]);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Medecin'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_medecin';
}
}
help me please for resolve this problem and thank you advanced
Since you've set departement field as nullable with 'required' => false,, the method $form->getData() in event listener may be either an instance of Departement entity or null if no departement was chosen.
You have to check if $form->getData() returns instance of your entity and
handle if it's not.
That would be something like:
$builder->addEventListener(
FormEvents::POST_SUBMIT,
function(FormEvent $event) {
$form= $event->getForm();
$formData = $form->getData();
if(! $formData instanceof Departement) {
//handle this case or just do nothing and return from the listener
return;
}
// here's the default case
$this->addVilleField($form->getParent(), $form->getData());
}
);
I'm trying to save a Game object with a Type object.
When I try to save with the form I get the following error:
Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
One Game can have 1 Type while Type can have many Games.
I've managed to isolate the problem, it works fine when Game doesn't have a relation with Type so I think it has to do something with the Type object.
GameController:
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\Game;
use AppBundle\Entity\Type;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
/**
* Game controller.
*
* #Route("game")
*/
class GameController extends Controller
{
/**
* Lists all game entities.
*
* #Route("/", name="game_index")
* #Method("GET")
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$games = $em->getRepository('AppBundle:Game')->findAll();
return $this->render('game/index.html.twig', array(
'games' => $games,
));
}
/**
* Creates a new game entity.
*
* #Route("/new", name="game_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$type = new Type();
$game = new Game();
$game->setType($type);
$form = $this->createForm('AppBundle\Form\GameType', $game);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($type);
$em->persist($game);
$em->flush($game);
return $this->redirectToRoute('game_show', array('id' => $game->getId()));
}
return $this->render('game/new.html.twig', array(
'game' => $game,
'form' => $form->createView(),
));
}
/**
* Finds and displays a game entity.
*
* #Route("/{id}", name="game_show")
* #Method("GET")
*/
public function showAction(Game $game)
{
$deleteForm = $this->createDeleteForm($game);
return $this->render('game/show.html.twig', array(
'game' => $game,
'delete_form' => $deleteForm->createView(),
));
}
/**
* Displays a form to edit an existing game entity.
*
* #Route("/{id}/edit", name="game_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, Game $game)
{
$deleteForm = $this->createDeleteForm($game);
$editForm = $this->createForm('AppBundle\Form\GameType', $game);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('game_edit', array('id' => $game->getId()));
}
return $this->render('game/edit.html.twig', array(
'game' => $game,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
/**
* Deletes a game entity.
*
* #Route("/{id}", name="game_delete")
* #Method("DELETE")
*/
public function deleteAction(Request $request, Game $game)
{
$form = $this->createDeleteForm($game);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->remove($game);
$em->flush($game);
}
return $this->redirectToRoute('game_index');
}
/**
* Creates a form to delete a game entity.
*
* #param Game $game The game entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm(Game $game)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('game_delete', array('id' => $game->getId())))
->setMethod('DELETE')
->getForm()
;
}
}
GameType.php:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class GameType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add( 'name', TextType::class);
$builder
->add( 'type', EntityType::class, [
'class' => 'AppBundle:Type',
'choice_label' => 'name',
'multiple' => false,
'expanded' => false
] );
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Game'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_game';
}
}
TypeType.php
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class TypeType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name') ;
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Type'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_type';
}
}
Game.php:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Game
*
* #ORM\Table(name="game")
* #ORM\Entity(repositoryClass="AppBundle\Repository\GameRepository")
*/
class Game
{
/**
* #ORM\ManyToOne(targetEntity="Type", inversedBy="games")
* #ORM\JoinColumn(name="type_id", referencedColumnName="id")
*/
private $type;
/**
* #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, unique=true)
*/
private $name;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Game
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #return mixed
*/
public function getType()
{
return $this->type;
}
/**
* #param mixed $type
*/
public function setType($type)
{
$this->type = $type;
}
}
Type.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Type
*
* #ORM\Table(name="type")
* #ORM\Entity(repositoryClass="AppBundle\Repository\TypeRepository")
*/
class Type
{
/**
* #ORM\OneToMany(targetEntity="Game", mappedBy="type")
*/
private $games;
public function __construct()
{
$this->games = new ArrayCollection();
}
/**
* #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)
*/
private $name;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Type
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #return mixed
*/
public function getGames()
{
return $this->games;
}
/**
* #param mixed $games
*/
public function setGames($games)
{
$this->games = $games;
}
public function addGame(Game $game)
{
$this->games->add($game);
$game->setType($this);
}
public function removeGame(Game $game)
{
$this->games->removeElement($game);
}
}
game/new.html.twig:
{% extends 'base.html.twig' %}
{% block content%}
<h1>Game creation</h1>
{{ form_start(form) }}
{{ form_widget(form.name) }}
{{ form_widget(form.type) }}
<input type="submit" value="Create" />
{{ form_end(form) }}
<ul>
<li>
Back to the list
</li>
</ul>
{% endblock %}
In the new action you should comment 3 lines
//$type = new Type();
$game = new Game();
//$game->setType($type);
$form = $this->createForm('AppBundle\Form\GameType', $game);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
//$em->persist($type);
$em->persist($game);
$em->flush($game);
The type will be set from framework because you are going to choose it from the dropdown
im new with symfony and i work with Symfony 2.7 and wamp server. I try to implement the upload method following the Symfony doc/cookbook.
Here is my entity:
<?php
namespace NoticiaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraint as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Imagem
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="NoticiaBundle\Repository\ImagemRepository")
* #ORM\HasLifecycleCallbacks
*/
class Imagem
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
public $path;
/**
* #ORM\OneToMany(targetEntity="Noticia", mappedBy="imagem")
*/
private $noticias = array();
public function __construct()
{
$this->noticias = new ArrayCollection();
}
public $file;
public function getUploadRootDir()
{
return __dir__.'/../../../../web/uploads';
}
public function getAbsolutePath()
{
return null === $this->path ? null : $this->getUploadRootDir().'/'.$this->path;
}
/**
* #ORM\Prepersist()
* #ORM\Preupdate()
*/
public function preUpload()
{
$this->tempFile = $this->getAbsolutePath();
$this->oldFile = $this->getPath();
if(null !== $this->file) $this->path = sha1(uniqid(mt_rand(),true)).'.'.$this->file->guessExtension();
}
/**
* #ORM\Postpersist()
* #ORM\Postupdate()
*/
public function upload()
{
if(null !==$this->file){
$this->file->move($this->getUploadRootDir(),$this->path);
unset($this->file);
if($this->oldFile !==null) unlink($this->tempFile);
}
}
/**
* #ORM\PreRemove()
*/
public function preRemoveUpload()
{
$this->tempFile = $this->getAbsolutePath();
}
/**
* #ORM\PostRemove()
*/
public function removeUpload()
{
if(file_exists($this->tempFile)) unlink($this->tempFile);
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
public function getPath()
{
return $this->path;
}
public function getName()
{
return $this->name;
}
}
My entity whith foreign key imagem
<?php
namespace NoticiaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Noticia
*
* #ORM\Table(name="NOTICIA")
* #ORM\Entity(repositoryClass="NoticiaBundle\Repository\NoticiaRepository")
* #ORM\HasLifecycleCallbacks
*/
class Noticia
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="titulo", type="string", length=255)
*/
private $titulo;
/**
* #var string
*
* #ORM\Column(name="noticia", type="string", length=255)
*/
private $noticia;
/**
* #ORM\ManyToOne(targetEntity="Imagem", cascade={"persist", "remove"})
* #ORM\JoinColumn(nullable=false)
*/
private $imagem;
/**
* #ORM\ManyToOne(targetEntity="Categoria", inversedBy="noticias")
* #ORM\JoinColumn(name="categoria_id", referencedColumnName="id")
*/
private $categoria;
/**
* #ORM\OneToMany(targetEntity="Comentario", mappedBy="noticia")
*/
private $comentarios = array();
public function __construct()
{
$this->comentarios = new ArrayCollection();
$this->setDtCadastro(new \DateTime());
$this->setDtAtualizacao(new \DateTime());
}
/**
* #var \DateTime
*
* #ORM\Column(name="dt_cadastro", type="datetime")
*/
private $dtCadastro;
/**
* #var \DateTime
*
* #ORM\Column(name="dt_atualizacao", type="datetime")
*/
private $dtAtualizacao;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set titulo
*
* #param string $titulo
* #return Noticia
*/
public function setTitulo($titulo)
{
$this->titulo = $titulo;
return $this;
}
/**
* Get titulo
*
* #return string
*/
public function getTitulo()
{
return $this->titulo;
}
/**
* Set noticia
*
* #param string $noticia
* #return Noticia
*/
public function setNoticia($noticia)
{
$this->noticia = $noticia;
return $this;
}
/**
* Get noticia
*
* #return string
*/
public function getNoticia()
{
return $this->noticia;
}
/**
* Set imagem
*
* #param string $imagem
* #return Noticia
*/
public function setImagem($imagem)
{
$this->imagem = $imagem;
return $this;
}
/**
* Get imagem
*
* #return string
*/
public function getImagem()
{
return $this->imagem;
}
/**
* Set categoria
*
* #param string $categoria
* #return Noticia
*/
public function setCategoria($categoria)
{
$this->categoria = $categoria;
return $this;
}
/**
* Get categoria
*
* #return string
*/
public function getCategoria()
{
return $this->categoria;
}
public function addComentario(Comentario $comentario)
{
$this->comentarios[] = $comentario;
return $this;
}
public function getComentarios()
{
return $this->comentarios;
}
/**
* Set dtCadastro
*
* #param \DateTime $dtCadastro
* #return Noticia
*/
public function setDtCadastro($dtCadastro)
{
$this->dtCadastro = $dtCadastro;
return $this;
}
/**
* Get dtCadastro
*
* #return \DateTime
*/
public function getDtCadastro()
{
return $this->dtCadastro;
}
/**
* Set dtAtualizacao
*
* #param \DateTime $dtAtualizacao
* #return Noticia
*/
public function setDtAtualizacao($dtAtualizacao)
{
$this->dtAtualizacao = $dtAtualizacao;
return $this;
}
/**
* Get dtAtualizacao
*
* #return \DateTime
*/
public function getdtAtualizacao()
{
return $this->dtAtualizacao;
}
/**
* #ORM\PreUpdate
*/
public function setDtAtualizacaoValue()
{
$this->setDtAtualizacao(new \DateTime());
}
/**
* Remove comentarios
*
* #param \NoticiaBundle\Entity\Comentario $comentarios
*/
public function removeComentario(\NoticiaBundle\Entity\Comentario $comentarios)
{
$this->comentarios->removeElement($comentarios);
}
}
my imagem form type
<?php
namespace NoticiaBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ImagemType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('file','file',array('required' => false));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'NoticiaBundle\Entity\Imagem'
));
}
/**
* #return string
*/
public function getName()
{
return 'noticiabundle_imagem';
}
}
Noticia FormType
<?php
namespace NoticiaBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use NoticiaBundle\Form\ImagemType;
class NoticiaType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('titulo',null, array('attr' => array('class' => 'form-control'),
'label_attr' => array('class' => 'control-label col-lg-2')
))
->add('imagem', new ImagemType(),
array('label_attr' => array('class' => 'control-label col-lg-2')
))
->add('noticia','textarea', array('attr' => array('class' => 'form-control', 'rows' => 15),
'label_attr' => array('class' => 'control-label col-lg-2')
))
->add('categoria', 'entity', array('attr' => array('class' => 'form-control'),
'label_attr' => array('class' => 'control-label col-lg-2'),
'class' => 'NoticiaBundle:Categoria',
'property' => 'nome',
'placeholder' => 'Escolha...',
))
->add('salvar', 'submit', array('attr' => array('class' => 'btn btn-primary pull-right')));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'NoticiaBundle\Entity\Noticia'
));
}
/**
* #return string
*/
public function getName()
{
return 'noticiabundle_noticia';
}
}
And the controler function to persist Noticias and imagens(upload files)
/**
* Add new Noticia.
*
* #Route("/noticia/novo", name="nova_noticia")
* #Template()
*/
public function novoAction(Request $request)
{
$form = $this->createForm(new NoticiaType(), new Noticia());
$form->handleRequest($request);
if ($form->isValid()) {
$noticia = $form->getData();
$noticia->setLogin($_SESSION['colaborador_login']);
$noticiaRepository = $this->getDoctrine()->getRepository('NoticiaBundle:Noticia');
try {
$noticiaRepository->novo($noticia);
$this->get('session')->getFlashBag()
->add('success', 'Iserido com sucesso!');
return $this->redirect($this->generateUrl('noticias_index'));
} catch (\Exception $e) {
$this->get('session')->getFlashBag()->add(
'danger', $e->getMessage()
);
}
}
return $this->render("NoticiaBundle:Noticia:formulario.html.twig",
array('form' => $form->createView()));
}
I change my entity upload file and now he is saving the right path, but the file is bot saving into the project directory
There is no easy way to test your code but just looking at it, the most obvious issue I see is that you don't call the function preUpload before saving the file.
You may need the following annotation for the preUpload function.
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/