I'm trying to upload multiple files on Symfony but when the form is submitted the form image field returns a null object like this
object(Doctrine\Common\Collections\ArrayCollection)#1455 (1) {
["elements":"Doctrine\Common\Collections\ArrayCollection":private]=>
array(1) {
[0]=>
object(AdminBundle\Entity\ImageNew)#1717 (5) {
["nom":"AdminBundle\Entity\ImageNew":private]=>
NULL
["path":"AdminBundle\Entity\ImageNew":private]=>
NULL
["idimage":"AdminBundle\Entity\ImageNew":private]=>
NULL
["categorie":"AdminBundle\Entity\ImageNew":private]=>
NULL
["file":"AdminBundle\Entity\ImageNew":private]=>
NULL
}
}
}
But when I get files directly inside the request files attributes file exist. I've tried to upload a file by accessing the attribute in the request, it works but it still wants to upload file via Symfony $form request handler.
That's my controller
public function addColorAction(Request $request, Article $article)
{
$couleur = new Couleur();
$form = $this->createForm('AdminBundle\Form\CouleurType', $couleur);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$files = $couleur->getImages();
echo "<pre>";
var_dump($files); die;
$imgs = $request->files->get("adminbundle_couleur")["images"];
foreach ($imgs as $img) {
$image = new ImageNew();
$image->setFile($img["file"]);
$image->upload();
$couleur->addImage($image);
$em->persist($image);
$em->flush();
}
$color_art_dispo = new CouleurArticleDispo();
$color_art_dispo->setEnStock(true);
$color_art_dispo->setArticle($article);
$color_art_dispo->setCouleur($couleur);
$em->persist($couleur);
$em->persist($color_art_dispo);
$em->flush();
return $this->redirectToRoute('article_index');
}
return $this->render(
'admin/article/couleur/new.html.twig', array(
'couleur' => $couleur,
'form' => $form->createView(),)
);
}
The couleur entity
class Couleur
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=255)
* #Assert\NotBlank(message="Veuillez entrer le nom de la couleur")
*/
private $nom;
/**
* #var string
*
* #ORM\Column(name="code_couleur", type="string", length=6)
* #Assert\NotBlank(message="Veuillez entrer le code couleur correspondant")
* #Assert\Length(
* min=6,
* max=6,
* minMessage="Le code couleur n'est pas correct.",
* maxMessage="Le code couleur n'est pas correct.",
* )
*/
private $codeCouleur;
/**
*
* #ORM\OneToMany(targetEntity="CouleurArticleDispo", mappedBy="_couleurs")
*/
private $colorArticles;
/**
* Many Colors have Many Images.
*
* #ORM\ManyToMany(targetEntity="ImageNew",cascade={"remove"})
* #ORM\JoinTable(name="color_images",joinColumns={#ORM\JoinColumn(name="color_id",referencedColumnName="id", onDelete="CASCADE")},
* inverseJoinColumns={#ORM\JoinColumn(name="image_id", referencedColumnName="idimage", onDelete="CASCADE")}
* )
*/
private $images;
public function __toString()
{
return (string) $this->getNom();
}
/**
* Class Constructor
*/
public function __construct()
{
$this->images = new ArrayCollection();
}
}
This is the image entity
class ImageNew
{
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=100)
*/
private $nom;
/**
* #var string
*
* #ORM\Column(name="path", type="string", length=255)
*/
private $path;
/**
* #var integer
*
* #ORM\Column(name="idimage",type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idimage;
/**
* #var \AdminBundle\Entity\Categorie
*
* #ORM\ManyToOne(targetEntity="AdminBundle\Entity\Categorie",cascade={"persist"},inversedBy="slides")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_categorie",referencedColumnName="idcategorie",nullable=true,onDelete="SET NULL")
* })
*/
private $categorie;
/**
* #Assert\NotNull()
* #Assert\File(
* maxSize = "6000k",
* mimeTypes = {"image/png", "image/jpg", "image/bmp"},
* mimeTypesMessage = "Please upload a valid Image File (PNG, JPEG or BMP)"
* )
*/
private $file;
public function __toString()
{
return (string) $this->getPath();
}
}
and this is the couleur type
class CouleurType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('nom')
->add('codeCouleur')
->add(
'images', CollectionType::class,
array(
'label' => 'Images de l\'article ayant cette couleur',
'entry_type' => ImageNewFileType::class,
'allow_add' => true,
'allow_delete' => true,
)
);
}
}
and finally the image type
class ImageNewFileType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'file', FileType::class,
[
'mapped' => false,
'required' => false,
'attr' => array(
'accept' => 'image/*',
)
]
);
}
}
I think you shouldn't add the mapped => false option in the ImageNewFileType.
https://symfony.com/doc/current/reference/forms/types/form.html#mapped
As you can see in the documentation the field is ignored when writing to the object.
the error was inside the ImageNewFileType, because of property 'mapped' => false, the form wasn't set uploaded files information in file field of ImageNew Entity, so I've replaced this :
class ImageNewFileType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'file', FileType::class,
[
'mapped' => false,
'required' => false,
'attr' => array(
'accept' => 'image/*',
)
]
);
}
}
by this:
class ImageNewFileType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'file', FileType::class,
[
'mapped' => true(or live this empty because by default it is true),
'required' => false,
'attr' => array(
'accept' => 'image/*',
)
]
);
}
}
Related
I am trying to submit a JSON through a complex form. I can't figure out what I am missing. The "normal" form is functioning. I am able to get serialized data with groups.
Class TaskBoard
class TaskBoard
{
/**
* #var integer $id id
*
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var \DateTime $createdTime createdTime
*
* #ORM\Column(type="datetime")
* #Assert\DateTime()
*/
private $createdTime;
/**
* #var \DateTime $lastUpdatedTime lastUpdatedTime
*
* #ORM\Column(type="datetime", nullable=true)
* #Assert\DateTime()
*/
private $lastUpdatedTime;
/**
* #var string $name name
*
* #ORM\Column(type="string", length=20)
* #Assert\Type("string")
* #Assert\NotBlank()
* #Assert\Length(
* min = 2,
* max = 20,
* minMessage = "The name must be at least {{ limit }} characters long",
* maxMessage = "The name cannot be longer than {{ limit }} characters"
* )
*/
private $name;
/**
* #var App\Entity\User $user user
*
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="taskboards", cascade={"persist"})
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
/**
* #var string $description description
*
* #ORM\Column(type="text", nullable=true)
* #Assert\Type("string")
*/
private $description;
/**
* #var App\Entity\Status $status status
*
* #ORM\ManyToOne(targetEntity="App\Entity\Status", inversedBy="taskboards", cascade={"persist"})
* #ORM\JoinColumn(name="status_id", referencedColumnName="id", nullable=false)
*/
private $status;
/**
* #var boolean $completed completed
*
* #ORM\Column(type="boolean")
*/
private $completed;
/**
* #var \DateTime $deadLine deadLine
*
* #ORM\Column(type="date", nullable=true)
* #Assert\DateTime()
* #Assert\GreaterThanOrEqual("today")
*/
private $deadLine;
Class Status
class Status
{
/**
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=20)
*/
private $name;
/**
* #ORM\OneToMany(targetEntity="App\Entity\TaskBoard", mappedBy="status", cascade={"persist"})
*/
public $taskboards;
Class User
class User extends BaseUser
{
/**
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="App\Entity\TaskBoard", mappedBy="user", cascade={"persist"})
*/
public $taskboards;
Form
class TaskBoardType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name', TextType::class)
->add('user', EntityType::class, array(
'class' => User::class,
'choice_label' => 'username',
)
)
->add('description', TextareaType::class, array(
'required' => false
))
->add('status', EntityType::class, array(
'class' => Status::class,
'choice_label' => 'name',
)
)
->add('deadLine', DateTimeType::class)
;
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults([
'data_class' => TaskBoard::class,
'csrf_protection' => false,
]);
}
Controller
class TaskBoardAPIController extends AbstractController {
public function postTaskBoard(Request $request) {
$form = $this->createForm(TaskBoardType::class, new TaskBoard());
$data = json_decode(
$request->getContent(), true
);
var_dump($data);
$form->submit($data);
if (!$form->isValid()) {
return new JsonResponse(
[
'status' => 'error',
'errors' => $form->getErrors(),
'form' => $form,
], JsonResponse::HTTP_BAD_REQUEST
);
}
$this->entityManager->persist($form->getData());
$this->entityManager->flush();
return new JsonResponse(
[
'status' => 'ok',
], JsonResponse::HTTP_CREATED
);
}
JSON sent
{
"name": "XXX",
"user": {
"id": 1,
"username": "BFA"
},
"description": "XXXXXXXXXXXXXXX",
"status": {
"id": 1,
"name": "To Do"
},
"completed": false
}
The form is not valid and blank in the JsonResponse.
I based myself on : https://codereviewvideos.com/course/beginners-guide-back-end-json-api-front-end-2018/video/symfony-4-json-api-form-submission
and Deserialize an entity with a relationship with Symfony Serializer Component
Thanks for your help.
What was wrong was the JSON input.
The form does this :
class TaskBoardType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name', TextType::class)
->add('user', EntityType::class, array(
'class' => User::class,
'choice_label' => 'username',
)
)
->add('description', TextareaType::class, array(
'required' => false
))
->add('status', EntityType::class, array(
'class' => Status::class,
'choice_label' => 'name',
)
)
->add('deadLine', DateTimeType::class)
;
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults([
'data_class' => TaskBoard::class,
'csrf_protection' => false,
]);
}
When checking the code generated from the form, this is the result :
<div>
<label for="task_board_user" class="required">User</label>
<select id="task_board_user" name="task_board[user]">
<option value="1">XXX</option>
<option value="2">XXX</option>
</select>
</div>
Thus the form is expecting directly an INT/ID.
By changing the JSON as follow it goes through validation :
{
"name": "XXXO",
"user": 1,
"description": "XXXXXXXXXXXXXXX",
"status": 1
}
Your forgot to handle and get form submission.
Note that you will need to get request data using something like
$form = $this->createFormBuilder($task)
... add fields
->getForm();
$form->handleRequest($request); // handling request
if ($form->isSubmitted() && $form->isValid()) {
// $form->getData() holds the submitted values
// but, the original `$task` variable has also been updated
$task = $form->getData();
// ... perform some action, such as saving the task to the database
// for example, if Task is a Doctrine entity, save it!
// $entityManager = $this->getDoctrine()->getManager();
// $entityManager->persist($task);
// $entityManager->flush();
return $this->redirectToRoute('...');
}
for more, see Handling Form Submissions
I work on a OneToMany association in my database. This association work perfectly when I try to add data from fixtures and when I try to return data from database.
The problem is with my FormType CommandType which does'nt work. Symfony and Doctrine return this error message :
An exception occurred while executing 'INSERT INTO command_product (quantity, command_id, product_id) VALUES (?, ?, ?)' with params [3, null, 1]:\n\nSQLSTATE[23000]: Integrity constraint violation: 1048 Column 'command_id' cannot be null
CommandType's code :
class CommandType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('establishment', EntityType::class, array(
'class' => Company::class,
'required' => true
))
->add('dateCreation', DateTimeType::class, array(
'widget' => 'single_text',
'format' => 'yyyy-MM-dd',
'required' => true
))
->add('contains', CollectionType::class, array(
'entry_type' => CommandProductType::class,
'required' => true,
'allow_add' => true
))
->add('state',TextType::class, array(
'required' => true
))
->add('totalAmount', MoneyType::class, array(
'required' => true
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Command::class
));
}
public function getBlockPrefix()
{
return 'appbundle_command';
}
}
CommandProductType's code :
class CommandProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('quantity', NumberType::class, array(
'required' => true
))
->add('product', EntityType::class, array(
'class' => Product::class,
'required' => true
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => CommandProduct::class
));
}
public function getBlockPrefix()
{
return 'appbundle_commandproduct';
}
}
Command's code class :
class Command
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var Company $establishment
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Company")
* #ORM\JoinColumn(name="establishment_id", referencedColumnName="id", nullable=false)
*/
private $establishment;
/**
* #var DateTime $dateCreation
*
* #ORM\Column(name="dateCreation", type="datetime", nullable=false)
* #Assert\Type("datetime")
*/
private $dateCreation;
/**
* #var string $state
*
* #ORM\Column(name="state", type="string", length=255, nullable=false)
* #Assert\Type("string")
*/
private $state;
/**
* #var float $totalAmount
*
* #ORM\Column(name="totalAmount", type="float", precision=10, scale=2, nullable=false)
* #Assert\NotBlank()
* #Assert\Type(type="float")
*/
private $totalAmount;
/**
* #var mixed $contains
*
* #ORM\OneToMany(targetEntity="AppBundle\Entity\CommandProduct", mappedBy="contain", cascade={"persist", "remove"})
*/
private $contains;
public function __construct()
{
$this->contains = new ArrayCollection();
}
/**
* #var CommandProduct $commandProduct
*/
public function addContain(CommandProduct $commandProduct = null)
{
$commandProduct->setContain($this);
$this->contains->add($commandProduct);
}
/**
* #param CommandProduct $commandProduct
*/
public function removeContain(CommandProduct $commandProduct)
{
if ($this->contains->contains($commandProduct)) {
$this->contains->removeElement($commandProduct);
}
}
}
CommandOrder's code class :
class CommandProduct
{
/**
* #var int $id
*
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var Command $contain
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Command", inversedBy="contains")
* #ORM\JoinColumn(name="command_id", referencedColumnName="id", nullable=false)
*/
private $contain;
/**
* #var int $quantity
*
* #ORM\Column(name="quantity", type="integer", nullable=true, options={"default": 1})
* #Assert\NotBlank()
* #Assert\Type(type="int")
*/
private $quantity;
/**
* #var Product $product
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Product")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
private $product;
}
I have two classes User.php and Group.php, extended from the classes defined in fosuserbundle .
Besides this I have a ManyToMany relation between them .
The idea of the application is when I add a new user, I assign one or many groups to user (I am using material design multi select option). The problem arises when user does not have any group(s) assigned (e.g when group option is empty). I get this javascript error in the console:
An invalid form control with name='user[groups][]' is not focusable.
So to resolve this issue, I need to provide a default value for group field. How to set a default user group if group is not selected ? My classes are defined as follow.
UserType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(
'username',
null,
array(
'attr' => array(
'placeholder' => 'username'
),
))
->add(
'email',
null,
array(
'attr' => array(
'placeholder' => 'email'
),
))
/*->add('groups', EntityType::class, array(
'class' => 'AppBundle\Entity\Group',
'choice_label' => 'name',
'expanded' => false,
'multiple' => false
)) */
->add('groups', EntityType::class, array(
'class' => 'AppBundle\Entity\Group',
'choice_label' => 'name',
'attr'=>array(
'class' => 'mdb-select'
),
'multiple' => true,
))
->add('plainPassword', RepeatedType::class, array(
'invalid_message' => 'Les mots de passe doivent être identiques.',
'first_options' => array('label' => 'Mot de passe'),
'second_options' => array('label' => 'Répétez le mot de passe'),
))
//<input id="input-id" type="file" class="file" multiple data-show-upload="false" data-show-caption="true">
->add('enabled', null, array(
'required' => false,
))
->add('imageFile',VichFileType::class, [
'required' => false,
'download_link' => true,
'attr'=>array(
'type' => 'file',
'onchange' => 'loadFile(event)'), // not mandatory, default is true
])
;
}
GroupEntity.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('roles', CollectionType::class, array(
'entry_type' => ChoiceType::class,
'entry_options' => array(
'attr' => array(
'class'=>'mdb-select colorful-select dropdown-default'
),
'choices' => array(
'Admin' => 'ROLE_ADMIN',
'USER' => 'ROLE_USER',
),
)
))
;
}
User.php
<?php
namespace AppBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #Vich\Uploadable
* #ORM\Entity
* #ORM\Table(name="fos_user")
* #UniqueEntity(fields="usernameCanonical", errorPath="username", message="fos_user.username.already_used", groups={"Default", "Registration", "Profile"})
* #UniqueEntity(fields="emailCanonical", errorPath="email", message="fos_user.email.already_used", groups={"Default", "Registration", "Profile"})
*/
class User extends BaseUser {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*
*/
protected $id;
/**
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Group", inversedBy="users", cascade={"remove"})
* #ORM\JoinTable(name="fos_user_user_group",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
protected $groups;
/**
* #ORM\Column(type="integer", length=6, options={"default":0})
*/
protected $loginCount = 0;
/**
* #var \DateTime
*
* #ORM\Column(type="datetime", nullable=true)
*/
protected $firstLogin;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="user_image", fileNameProperty="imageName")
*
* #var File
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255,nullable=true)
*
* #var string
*/
private $imageName;
/**
* #ORM\Column(type="datetime",nullable=true)
*
* #var \DateTime
*/
private $updatedAt;
public function __construct() {
parent::__construct();
$this->enabled = true;
$this->groups = new ArrayCollection();
}
}
Group.php
namespace AppBundle\Entity;
use FOS\UserBundle\Model\Group as BaseGroup;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="fos_group")
*/
class Group extends BaseGroup
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\User", mappedBy="groups")
*
*
*/
protected $users;
/**
* #var string
*/
protected $name;
/**
* #var array
*/
protected $roles;
/**
* Group constructor.
*
* #param string $name
* #param array $roles
*/
public function __construct($name, $roles = array())
{
$this->name = $name;
$this->roles = $roles;
}
}
You need to pass the default data when creating the form. For example in your controller you'll have:
$user = new User();
// Add default groups to the $user
// ...
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
// ...
}
You can achieve that by adding a 'POST_SET_DATA' or 'PRE_SUBMIT' form event to assign a group to the user if there aren't any groups in the form data.
$builder->addEventListener(FormEvents::POS_SET_DATA, function (FormEvent $event) {
$user = $event->getData();
$form = $event->getForm();
if (!$user->getGroups->count() > 0) {
//...
}
});
http://symfony.com/doc/current/form/dynamic_form_modification.html
https://symfony.com/doc/current/form/events.html
you could also use a lifecycle callback for your user entity
http://symfony.com/doc/current/doctrine/lifecycle_callbacks.html
or directly modify the object in your controller (#martin 's answer)
This error appears when I try to persist my entity :
Warning: spl_object_hash() expects parameter 1 to be object, integer
given in
C:\wamp\www\projet\vendor\doctrine\orm\lib\Doctrine\ORM\UnitOfWork.php
line 1601
This is my entity Site :
/**
* Etablissement
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Intranet\RhBundle\Entity\SiteRepository")
*/
class Site {
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id; /**
* #ORM\OneToMany(targetEntity="Intranet\RhBundle\Entity\SiteEtablissement",
mappedBy="site", cascade={"persist", "remove"}, orphanRemoval=true)
* */
private $siteEtablissements;
}
This is my entity Etablissement :
/**
* Etablissement
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Intranet\RhBundle\Entity\EtablissementRepository")
*/
class Etablissement {
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
}
And the entity for the relation :
/**
* #ORM\Entity(repositoryClass="Intranet\RhBundle\Entity\SiteEtablissementRepository")
*/
class SiteEtablissement {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Intranet\RhBundle\Entity\Site", inversedBy="siteEtablissements")
* #ORM\JoinColumn(name="site_id", referencedColumnName="id")
*/
private $site;
/**
* #ORM\ManyToOne(targetEntity="Intranet\RhBundle\Entity\Etablissement")
* #ORM\JoinColumn(name="etablissement_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $etablissement;
}
So I don't understand why I have this error, my mapping seems to be ok. I don't have any entity error and I have no error before to persist $site in my controller.
This is my controller :
public function gererEtablissementAction(Request $request, Site $site) {
$form = $this->createForm(new GererSiteEtabType(), $site);
if ($request->getMethod() == 'POST') {
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
foreach ($site->getSiteEtablissements() as $sitEtab)
if (is_null($sitEtab->getAutor()))
$sitEtab->setAutor($this->getUser());
$em->persist($site);
$em->flush();
$this->get('session')->getFlashBag()->add('success', "Les établissement du site " . $site->getNom() . " ont été modifiés avec succès !");
return $this->redirect($this->generateUrl('intranet_rh_homepage_employes'));
} else
$this->get('session')->getFlashBag()->add('danger', "Erreur de formulaire !");
}
return $this->render('IntranetRhBundle:Site:gererEtablissement.html.twig', array('site' => $site, 'form' => $form->createView()));
}
When I print $site->getSiteEtablissements, there are Site and Etablissement on each side of each object...
This is the build form :
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('siteEtablissements', 'collection', array(
'type' => new SiteEtablissementType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'required' => false
))
;
}
And the subform :
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('etablissement', 'entity', array(
'label' => 'Etablissement :',
'class' => 'IntranetRhBundle:Etablissement',
'property' => 'nom',
'query_builder' => function(EtablissementRepository $er) {
// récupère les établissements triés par ordre alpabétique croissant de nom
return $er->createQueryBuilder('e')
->orderBy('e.nom', 'ASC');
},
'attr' => array('class' => 'form-control')
))
;
}
I find the error : a bad initialsiation of Autor.
Autor was initialise at "0" and in the loop I test if is_null. So 0 is not null and when it persists, there is an error ebcause there is no user with id 0...
I have problem with form collection. I get an error:
Notice: Array to string conversion in /home/.../vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php line 103
i tried foreach (like is in doctrine documentation) and perist each object, but I get an error:
The class 'Doctrine\Common\Collections\ArrayCollection' was not found in the chain configured namespaces FOS\UserBundle\Entity, Ix\UserBundle\Entity, Ix\x\Entity, FOS\UserBundle\Model
Below is my code:
Entity:
/**
* #ORM\Entity
* #ORM\Table(name="availability")
*/
class Availability
{
public function __construct()
{
$this->availabilityFlexible = new \Doctrine\Common\Collections\ArrayCollection();
$this->availabilitySession = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="description", type="string", length=255, nullable=true)
*/
protected $description;
/**
* #ORM\OneToMany(targetEntity="AvailabilityFlexible", mappedBy="availability", cascade={"persist", "remove"})
*/
protected $availabilityFlexible;
/**
* #ORM\OneToOne(targetEntity="AvailabilityFull", mappedBy="availability", cascade={"persist", "remove"})
*/
protected $availabilityFull;
/**
* #ORM\OneToMany(targetEntity="AvailabilitySession", mappedBy="availability", cascade={"persist", "remove"})
*/
protected $availabilitySession;
// AvailabilityFlexible.php
/**
* #ORM\ManyToOne(targetEntity="Availability", inversedBy="availabilityFlexible", cascade={"persist"})
* #ORM\JoinColumn(name="availability_id", referencedColumnName="id")
*/
protected $availability;
// AvailabilityFull.php
/**
* #ORM\OneToOne(targetEntity="Availability", inversedBy="availabilityFull", cascade={"persist"})
* #ORM\JoinColumn(name="availability_id", referencedColumnName="id")
*/
protected $availability;
// AvailabilitySession.php
/**
* #ORM\ManyToOne(targetEntity="Availability", inversedBy="availabilitySession", cascade={"persist"})
* #ORM\JoinColumn(name="availability_id", referencedColumnName="id")
*/
protected $availability;
Form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('description')
->add('AvailabilitySession', 'collection', array(
'type' => new AvailabilitySessionFormType(),
'allow_add' => true,
'prototype' => true,
'by_reference' => false,
'allow_delete' => true,
))
->add('AvailabilityFull', new AvailabilityFullFormType())
->add('AvailabilityFlexible', 'collection', array(
'type' => new AvailabilityFlexibleFormType(),
'allow_add' => true,
'by_reference' => false,
'allow_delete' => true,
));
}
Controller:
public function addAvailabilityAction(Request $request)
{
$availability = new Availability;
$availability->getAvailabilityFlexible()->add(new AvailabilityFlexible);
$availability->getAvailabilityFlexible()->add(new AvailabilityFlexible);
$form = $this->createForm(new AvailabilityFormType(), $availability);
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
$availability = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->perist($availability);
$em->flush();
}
}
}
Properties $availability are in different class.
AvailabilityFlexible.php
AvailabilityFull.php
AvailabilitySession.php
This is relationship to Availability Entity.