In my Symdony2 project I've two related entities: "Reglement and "Article". This should be many-to-one relationship, because each "Reglement" can have many "Articles", and each "Article" can belongs to one "Reglement".
Moreover, I need a user interface to manage Reglement and Articles. So, when adding a Reglement, user should be able to add many articles it belongs.
I've already achieved this by setting up a One-To-Many relation in my Doctrine entites. Everything is working like a charm, including user interface build on custom form types in Symfony2 (I've used "Collection" form field type to allow user to add "Articles" in "Reglement). The only problem I've is that I can save only the last article in the database !!
Here is my "Reglement" entity source code:
<?php
namespace GestionEnvironnementale\ISO14001Bundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Reglement
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="GestionEnvironnementale\ISO14001Bundle\Entity\ReglementRepository")
*/
class Reglement
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="domaineApplication", type="string", length=255)
*/
private $domaineApplication;
/**
* #var string
*
* #ORM\Column(name="texteLegislatif", type="text")
*/
private $texteLegislatif;
/**
* #var string
*
* #ORM\Column(name="contenuText", type="text")
*/
private $contenuText;
/**
* #ORM\OneToMany(targetEntity="GestionEnvironnementale\ISO14001Bundle\Entity\Article", cascade={"persist"}, mappedBy="reglement")
*/
private $articles;
public function __construct()
{
$this->articles = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getArticles()
{
return $this->articles;
}
public function setArticles(ArrayCollection $articles)
{
foreach ($articles as $article) {
$article->addReglement($this);
}
$this->articles = $articles;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set domaineApplication
*
* #param string $domaineApplication
* #return Reglement
*/
public function setDomaineApplication($domaineApplication)
{
$this->domaineApplication = $domaineApplication;
return $this;
}
/**
* Get domaineApplication
*
* #return string
*/
public function getDomaineApplication()
{
return $this->domaineApplication;
}
/**
* Set texteLegislatif
*
* #param string $texteLegislatif
* #return Reglement
*/
public function setTexteLegislatif($texteLegislatif)
{
$this->texteLegislatif = $texteLegislatif;
return $this;
}
/**
* Get texteLegislatif
*
* #return string
*/
public function getTexteLegislatif()
{
return $this->texteLegislatif;
}
/**
* Set contenuText
*
* #param string $contenuText
* #return Reglement
*/
public function setContenuText($contenuText)
{
$this->contenuText = $contenuText;
return $this;
}
/**
* Get contenuText
*
* #return string
*/
public function getContenuText()
{
return $this->contenuText;
}
/**
* Add articles
*
* #param \GestionEnvironnementale\ISO14001Bundle\Entity\Article $articles
* #return Reglement
*/
public function addArticle(\GestionEnvironnementale\ISO14001Bundle\Entity\Article $articles)
{
$this->articles[] = $articles;
return $this;
}
/**
* Remove articles
*
* #param \GestionEnvironnementale\ISO14001Bundle\Entity\Article $articles
*/
public function removeArticle(\GestionEnvironnementale\ISO14001Bundle\Entity\Article $articles)
{
$this->articles->removeElement($articles);
}
}
And here is my Article entity source code:
<?php
namespace GestionEnvironnementale\ISO14001Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Article
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="GestionEnvironnementale\ISO14001Bundle\Entity\ArticleRepository")
*/
class Article
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="GestionEnvironnementale\ISO14001Bundle\Entity\Reglement", inversedBy="articles")
* #ORM\JoinColumn(nullable=false)
*/
private $reglement;
/**
* #var string
*
* #ORM\Column(name="exigenceArticle", type="string", length=255)
*/
private $exigenceArticle;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set exigenceArticle
*
* #param string $exigenceArticle
* #return Article
*/
public function setExigenceArticle($exigenceArticle)
{
$this->exigenceArticle = $exigenceArticle;
return $this;
}
/**
* Get exigenceArticle
*
* #return string
*/
public function getExigenceArticle()
{
return $this->exigenceArticle;
}
/**
* Set reglement
*
* #param \GestionEnvironnementale\ISO14001Bundle\Entity\Reglement $reglement
* #return Article
*/
public function setReglement(\GestionEnvironnementale\ISO14001Bundle\Entity\Reglement $reglement)
{
$this->reglement = $reglement;
return $this;
}
/**
* Get reglement
*
* #return \GestionEnvironnementale\ISO14001Bundle\Entity\Reglement
*/
public function getReglement()
{
return $this->reglement;
}
public function addReglement(Reglement $reglement)
{
if (!$this->reglements->contains($reglement)) {
$this->reglements->add($reglement);
}
}
}
and here is my reglement form :
<?php
namespace GestionEnvironnementale\ISO14001Bundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ReglementType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('domaineApplication')
->add('texteLegislatif')
->add('contenuText')
->add('articles', 'collection', array(
'type' => new ArticleType(),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'by_reference' => false,
));
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'GestionEnvironnementale\ISO14001Bundle\Entity\Reglement'
));
}
/**
* #return string
*/
public function getName()
{
return 'gestionenvironnementale_iso14001bundle_reglementtype';
}
}
and my article form :
<?php
namespace GestionEnvironnementale\ISO14001Bundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ArticleType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('exigenceArticle')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'GestionEnvironnementale\ISO14001Bundle\Entity\Article'
));
}
/**
* #return string
*/
public function getName()
{
return 'gestionenvironnementale_iso14001bundle_article';
}
}
And here is part of my ReglementController source code:
public function ajouterReglementAction()
{
$reglement = new Reglement();
$form = $this->createForm(new ReglementType(), $reglement);
$request = $this->getRequest();
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$reglement->getArticles()->clear();
$em = $this->getDoctrine()->getManager();
$em->persist($reglement);
$em->flush();
foreach ($form->get('articles')->getData() as $ac) {
$ac->setReglement($reglement);
$em->persist($ac);
}
$em->flush();
$this->get('session')->getFlashBag()->add('info', 'Reglement bien enregistré');
return $this->redirect( $this->generateUrl('reglement_voir', array('id' => $reglement->getId())));
}
}
return $this->render('ISO14001Bundle:Reglements:ajouter.html.twig', array(
'form' => $form->createView()
));
}
finnally the form view source code :
<div class="well">
<form method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<br/> <input type="submit" value="Envoyer" class="btn btn-primary" />
</form>
<script src="{{ asset('js/jquery-2.1.1.min.js') }}"></script>
<script type="text/javascript">
$(document).ready(function() {
var $container = $('div#gestionenvironnementale_iso14001bundle_reglementtype_articles');
var $lienAjout = $('Ajouter un article');
$container.append($lienAjout);
$lienAjout.click(function(e) {
ajouterArticle($container);
e.preventDefault();
return false;
});
var index = $container.find(':input').length;
if (index == 0) {
ajouterArticle($container);
} else {
$container.children('div').each(function() {
ajouterLienSuppression($(this));
});
}
function ajouterArticle($container) {
var $prototype = $($container.attr('data-prototype').replace(/__name__label__/g, 'Article n°' + (index+1))
.replace(/\$\$name\$\$/g, index));
ajouterLienSuppression($prototype);
$container.append($prototype);
index++;
}
function ajouterLienSuppression($prototype) {
$lienSuppression = $('Supprimer');
$prototype.append($lienSuppression);
$lienSuppression.click(function(e) {
$prototype.remove();
e.preventDefault();
return false;
});
}
});
I hope you can help me ;)
hi everyone I found the solution of my problem ^_^
the error is in line 27 of form view, there must be __name__ instead of $$name$$ as follows :
function ajouterArticle($container) {
var $prototype = $($container.attr('data-prototype').replace(/__name__label__/g, 'Article n°' + (index+1))
.replace(/__name__/g, index));
ajouterLienSuppression($prototype);
$container.append($prototype);
index++;
}
good luck ;)
Related
I need your help on my problem for saving my data in table.
I use fosUserBundle and have different user types (Admin, Pro, Client) that are classes extending a base User entity.
I also have a Language entity linked to the User with a one-to-many association.
To subscribe, a userClient needs to check by checkbox the language(s) that he speaks.
The form page is ok, it displays the UserClient form (+ the parent User form) with the list of languages as checkboxes.
The problem is the data saved in table.
I have the same values in the language column:
O:43:"Doctrine\Common\Collections\ArrayCollection":1:{s:53:"Doctrine\Common\Collections\ArrayCollectionelements";a:2:{i:0;O:32:"LanguagesBundle\Entity\Languages":10:{s:36:"LanguagesBundle\Entity\Languagesid";i:2;s:38:"LanguagesBundle\Entity\Languagesname";s:7:"English";s:44:"LanguagesBundle\Entity\Languagesshort_slug";s:2:"en";s:43:"LanguagesBundle\Entity\Languageslong_slug";s:5:"en_EN";s:43:"LanguagesBundle\Entity\LanguagesisDefault";b:0;s:43:"LanguagesBundle\Entity\LanguagesupdatedAt";O:8:"DateTime":3:{s:4:"date";s:26:"2018-04-20 22:46:48.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:12:"Europe/Paris";}s:43:"LanguagesBundle\Entity\LanguagesimageFile";N;s:39:"LanguagesBundle\Entity\Languagesimage";s:39:"Flag_of_United_Kingdom_-_Circle-512.png";s:43:"LanguagesBundle\Entity\LanguagesimageSize";i:37621;s:44:"LanguagesBundle\Entity\LanguagesuserClient";N;}i:1;O:32:"LanguagesBundle\Entity\Languages":10:{s:36:"LanguagesBundle\Entity\Languagesid";i:1;s:38:"LanguagesBundle\Entity\Languagesname";s:9:"Français";s:44:"LanguagesBundle\Entity\Languagesshort_slug";s:2:"fr";s:43:"LanguagesBundle\Entity\Languageslong_slug";s:5:"fr_FR";s:43:"LanguagesBundle\Entity\LanguagesisDefault";b:1;s:43:"LanguagesBundle\Entity\LanguagesupdatedAt";O:8:"DateTime":3:{s:4:"date";s:26:"2018-04-20 22:45:50.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:12:"Europe/Paris";}s:43:"LanguagesBundle\Entity\LanguagesimageFile";N;s:39:"LanguagesBundle\Entity\Languagesimage";s:31:"Flag_of_France_-_Circle-512.png";s:43:"LanguagesBundle\Entity\LanguagesimageSize";i:23352;s:44:"LanguagesBundle\Entity\LanguagesuserClient";N;}}}
Here's my code:
User.php
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use UserBundle\Entity\UserAdmin;
use UserBundle\Entity\UserProfessional;
use UserBundle\Entity\UserClient;
use UserBundle\Entity\Adress;
/**
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="discr", type="string")
* #ORM\DiscriminatorMap({"client" = "UserClient", "professional"="UserProfessional", "admin"="UserAdmin"})
*/
abstract class User extends BaseUser {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255)
*/
protected $firstname;
//[...] getters and setters
Entity: UserClient.php
<?php
// src/UserBundle/Entity/UserGuest.php
namespace UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
*/
class UserClient extends User {
/**
* #ORM\Column(type="array")
* #ORM\OneToMany(targetEntity="LanguagesBundle\Entity\Languages", mappedBy="userClient")
*/
private $languages;
public function __construct() {
parent::__construct();
$this->languages = new ArrayCollection();
}
/**
* Set languages
*
* #param array $languages
*
* #return UserClient
*/
public function setLanguages($languages)
{
$this->languages = $languages;
}
/**
* Get languages
*
* #return array
*/
public function getLanguages()
{
return $this->languages;
}
/**
* Add language
*
* #param \LanguagesBundle\Entity\Languages $language
*
* #return UserClient
*/
public function addLanguage(LanguagesBundle\Entity\Languages $language)
{
$this->languages[] = $language;
return $this;
}
/**
* Remove language
*
* #param \LanguagesBundle\Entity\Languages $language
*/
public function removeLanguage(\LanguagesBundle\Entity\Languages $language)
{
$this->languages->removeElement($language);
}
}
Entity Languages.php
<?php
namespace LanguagesBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #ORM\Entity
*
* #Vich\Uploadable
*/
class Languages
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var string
*
* #ORM\Column(type="string")
* #Assert\NotBlank()
*/
private $name;
/**
* #ORM\Column(type="string", length=2, unique=true)
*/
private $short_slug;
/**
* #var string
*
* #ORM\Column(type="string", length=5, unique=true)
* #Assert\NotBlank()
*/
private $long_slug;
/**
* #var string
*
* #ORM\Column(type="boolean", nullable=true)
*/
private $isDefault;
/**
* #ORM\Column(type="datetime")
* #var \DateTime
*/
private $updatedAt;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Assert\File(
* maxSize="1M",
* mimeTypes={"image/png", "image/jpeg", "image/pjpeg"}
* )
* #Vich\UploadableField(mapping="language_images", fileNameProperty="image", size="imageSize")
* #var File
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255, nullable = true)
* #var string
*/
private $image;
/**
* #ORM\Column(type="integer")
*
* #var integer
*/
private $imageSize;
/**
* #ORM\ManyToOne(targetEntity="UserBundle\Entity\UserClient", inversedBy="languages")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $userClient;
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* #param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*/
public function setImageFile(?File $image = null): void
{
$this->imageFile = $image;
if (null !== $image) {
// 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 \DateTimeImmutable();
}
}
public function getImageFile()
{
return $this->imageFile;
}
/**
* Constructor
*/
public function __construct()
{
$this->updatedAt = new \DateTime();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Languages
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set shortSlug
*
* #param string $shortSlug
*
* #return Languages
*/
public function setShortSlug($shortSlug)
{
$this->short_slug = $shortSlug;
return $this;
}
/**
* Get shortSlug
*
* #return string
*/
public function getShortSlug()
{
return $this->short_slug;
}
/**
* Set longSlug
*
* #param string $longSlug
*
* #return Languages
*/
public function setLongSlug($longSlug)
{
$this->long_slug = $longSlug;
return $this;
}
/**
* Get longSlug
*
* #return string
*/
public function getLongSlug()
{
return $this->long_slug;
}
/**
* Set isDefault
*
* #param boolean $isDefault
*
* #return Languages
*/
public function setIsDefault($isDefault)
{
$this->isDefault = $isDefault;
return $this;
}
/**
* Get isDefault
*
* #return boolean
*/
public function getIsDefault()
{
return $this->isDefault;
}
/**
* Set updatedAt
*
* #param \DateTime $updatedAt
*
* #return Languages
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* #return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* Set image
*
* #param string $image
*
* #return Languages
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
/**
* Set imageSize
*
* #param integer $imageSize
*
* #return Languages
*/
public function setImageSize($imageSize)
{
$this->imageSize = $imageSize;
return $this;
}
/**
* Get imageSize
*
* #return integer
*/
public function getImageSize()
{
return $this->imageSize;
}
/**
* Set userClient
*
* #param \UserBundle\Entity\UserClient $userClient
*
* #return Languages
*/
public function setUserClient(\UserBundle\Entity\UserClient $userClient = null)
{
$this->userClient = $userClient;
return $this;
}
/**
* Get userClient
*
* #return \UserBundle\Entity\UserClient
*/
public function getUserClient()
{
return $this->userClient;
}
/**
* {#inheritdoc}
*/
public function __toString()
{
return $this->getName() ?: '-';
}
}
My FormType: RegistrationTypeClient.php
<?php
// src/UserBundle/Form/UserContactFormType.php
namespace UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use LanguagesBundle\Services\LanguagesService;
use LanguagesBundle\Entity\Languages ;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
class RegistrationClientType extends AbstractType {
protected $service;
public function buildForm(FormBuilderInterface $builder, array $options) {
parent::buildForm($builder, $options);
$builder
->add('languages', EntityType::class, [
'class' => 'LanguagesBundle:Languages',
'choice_label' => 'name',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.name', 'ASC');
},
'label' => 'Langues',
'expanded' => true,
'multiple' => true,
])
;
}
public function getParent() {
// on inclut le formulaire de base d'inscription utilisateur
return 'UserBundle\Form\RegistrationType';
}
public function getBlockPrefix() {
return 'app_user_registration_client';
}
// For Symfony 2.x
public function getName() {
return $this->getBlockPrefix();
}
public function configureOptions(OptionsResolver $resolver) {
$resolver
->setDefaults(array(
'data_class' => \UserBundle\Entity\UserClient::class,
))
//->setRequired('service_languages');
;
}
}
And my Controller:
public function registerClientAction(Request $request) {
/** #var $formFactory FactoryInterface */
//$formFactory = $this->get('fos_user.registration_pro.form.factory');
/** #var $userManager UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
/** #var $dispatcher EventDispatcherInterface */
$dispatcher = $this->get('event_dispatcher');
$user = new UserClient();
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $this->createForm(RegistrationClientType::class, $user);
$form->setData($user);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event);
if (null !== $response = $event->getResponse()) {
return $response;
}
}
return $this->render('UserBundle\Registration\register_client.html.twig', array(
'form' => $form->createView(),
));
}
Here's a picture showing the data saved in the table
I need the languages to be stored in the database as an array for userClient.
Could you help me please.
Thank's for re-edit my question Philip-B-
Thank's for your reading also.
I have resolve my problem by adding a foreach to transform my object to array:
The code is in my controller:
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
foreach ($user->getLanguages() as $value) {
$langue[] = $value->getShortSlug();
}
$user->setLanguages($langue);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
I have a form customer registration type with an embed address form (billingAddress and an other optional ShippingAddress).
If the user don't check the "different shipping Address" checkbox, I should have only one addrress in my db address table. Even so I get two differents addresses in my Address table (with the same informations).
However, I check with "addAddress" if the address is already exist before add a new address. In fact in my Customer FormType, I copy billingAddress form data in shippingAdress form but in hasAdress method, $this->addresses->contains($address) return always false. I don't understand why...
Thanks
Here the code:
Customer Class
<?php
namespace DRMS\CustomerBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use DRMS\AddressingBundle\Entity\Address;
/**
* DRMS\CustomerBundle\Entity\Customer
*
* #ORM\Entity(repositoryClass="DRMS\CustomerBundle\Repository\CustomerRepository")
* #ORM\Table(name="customer", uniqueConstraints={#ORM\UniqueConstraint(name="customer_id_UNIQUE", columns={"customer_id"})})
*/
class Customer
{
/**
* #ORM\Id
* #ORM\Column(type="integer", name="customer_id")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $customerId;
// Others attributes
// ...
/**
* #ORM\OneToOne(targetEntity="DRMS\AddressingBundle\Entity\Address")
* #ORM\JoinColumn(name="billing_address_id", referencedColumnName="address_id")
*/
protected $billingAddress;
/**
* #ORM\OneToOne(targetEntity="DRMS\AddressingBundle\Entity\Address")
* #ORM\JoinColumn(name="shipping_address_id", referencedColumnName="address_id")
*/
protected $shippingAddress;
/**
* #ORM\OneToMany(targetEntity="DRMS\AddressingBundle\Entity\Address", mappedBy="customer", cascade={"remove", "persist"})
** ORM\JoinColumn(name="customer_id", referencedColumnName="customer_id", onDelete="CASCADE")
*/
protected $addresses;
public function __construct()
{
$this->addresses = new ArrayCollection();
}
/**
* Set the value of customerId.
*
* #param integer $customerId
* #return \DRMS\CustomerBundle\Entity\Customer
*/
public function setCustomerId($customerId)
{
$this->customerId = $customerId;
return $this;
}
/**
* Get the value of customerId.
*
* #return integer
*/
public function getCustomerId()
{
return $this->customerId;
}
// Others Getters/Setters
// ...
/**
* Set billingAddress
*
* #param \DRMS\AddressingBundle\Entity\Address $billingAddress
* #return Customer
*/
public function setBillingAddress(Address $billingAddress = null)
{
$this->billingAddress = $billingAddress;
if (null !== $billingAddress && !$this->hasAddress($billingAddress)) {
$this->addAddress($billingAddress);
}
return $this;
}
/**
* Get billingAddress
*
* #return \DRMS\AddressingBundle\Entity\Address
*/
public function getBillingAddress()
{
return $this->billingAddress;
}
/**
* Set shippingAddress
*
* #param \DRMS\AddressingBundle\Entity\Address $shippingAddress
* #return Customer
*/
public function setShippingAddress(Address $shippingAddress = null)
{
$this->shippingAddress = $shippingAddress;
if (null !== $shippingAddress && !$this->hasAddress($shippingAddress)) {
$this->addAddress($shippingAddress);
}
return $this;
}
/**
* Get shippingAddress
*
* #return \DRMS\AddressingBundle\Entity\Address
*/
public function getShippingAddress()
{
return $this->shippingAddress;
}
/**
* Add Address entity to collection (one to many).
*
* #param \DRMS\AddressingBundle\Entity\Address $address
* #return \DRMS\CustomerBundle\Entity\Customer
*/
public function addAddress(Address $address)
{
if (!$this->hasAddress($address)) {
$this->addresses->add($address);
$address->setCustomer($this);
}
return $this;
}
/**
* Remove Address
*
* #param \DRMS\AddressingBundle\Entity\Address $address
* #return \DRMS\CustomerBundle\Entity\Customer
*/
public function removeAddress(Address $address) {
$this->addresses->removeElement($address);
return $this;
}
/**
* Get Address entity collection (one to many).
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getAddresses()
{
return $this->addresses;
}
/**
* Has address
*
* #param \DRMS\AddressingBundle\Entity\Address $address
* #return bool
*/
public function hasAddress(Address $address)
{
return $this->addresses->contains($address);
}
}
Address class
<?php
namespace DRMS\AddressingBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* DRMS\AddressingBundle\Entity\Address
*
* #ORM\Entity(repositoryClass="DRMS\AddressingBundle\Repository\AddressRepository")
* #ORM\Table(name="address"), uniqueConstraints={#ORM\UniqueConstraint(name="customer_adress_UNIQUE", columns={"customer_id","address_id"})}
*/
class Address
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $address_id;
// Others attributes
// ...
/**
* #ORM\ManyToOne(targetEntity="DRMS\CustomerBundle\Entity\Customer", inversedBy="addresses", cascade={"remove"})
* #ORM\JoinColumn(name="customer_id", referencedColumnName="customer_id", onDelete="CASCADE")
*/
protected $customer;
/**
* Get the value of address_id.
*
* #return integer
*/
public function getAddressId()
{
return $this->address_id;
}
/**
* Set customer
*
* #param \DRMS\CustomerBundle\Entity\Customer $customer
* #return Address
*/
public function setCustomer(\DRMS\CustomerBundle\Entity\Customer $customer)
{
$this->customer = $customer;
return $this;
}
/**
* Get customer
*
* #return \DRMS\CustomerBundle\Entity\Customer
*/
public function getCustomer()
{
return $this->customer;
}
}
Customer FormType
<?php
# src\DRMS\CustomerBundle\Form\Type\CustomerType.php
namespace DRMS\CustomerBundle\Form\Type;
/**
* Description of CustomerType
*
*/
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
class CustomerType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$data = $event->getData();
if (!array_key_exists('differentShippingAddress', $data) || false === $data['differentShippingAddress']) {
$data['shippingAddress'] = $data['billingAddress'];
$event->setData($data);
}
});
$builder->add('customerName', null)
->add('customerFirstname', null)
->add('phone')
->add('mobilePhone')
->add('billingAddress', 'drms_address', array(
'label' => 'drms.form.customer.billing_address',
))
->add('differentShippingAddress', 'checkbox', array(
'mapped' => false,
'label' => 'drms.form.customer.different_shipping_address',
'required' => false,
))
->add('shippingAddress', 'drms_address', array(
'label' => 'drms.form.customer.shipping_address',
))
;
}
/**
* #param OptionsResolverInterface $resolver
*
* If checkbox vatNumberOwner is checked, apply "vat_number_required" validation group for activate Vat Number test
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'DRMS\CustomerBundle\Entity\Customer',
'validation_groups' => function(FormInterface $form) {
$validation_groups = array('Registration');
if($form->get('differentShippingAddress')->getData() == true) {
$validation_groups[] = 'ShippingAddressRequired';
}
return $validation_groups;
},
));
}
public function getName()
{
return 'drms_customer';
}
}
contains() is implemented like this https://github.com/doctrine/collections/blob/master/lib/Doctrine/Common/Collections/ArrayCollection.php#L189 That means you are doing a strict comparison on the object identity. Since the address object is created by the form and not managed by Doctrine in the identity map it will not compare to the objects created by Doctrine. Since custom collections are not supported i suggest you change the in_array logic to be not strict and put it in your entity directly.
I'm trying to create a form to insert "questions" that can have one or more "answers". So I want to add an embed form for the Answer entity.
It seems to work because I see the Question form, but only the string "Answers" is displayed at the bottom of my form, not the fields.
Here is my controller action :
public function addQuestionAction(Category $category)
{
$question = new Question();
$form = $this->createForm(new QuestionType(), $question);
$request = $this->get('request');
if ($request->getMethod() === 'POST') {
$form->bind($request);
$question->setCategory($category);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($question);
$em->flush();
return $this->redirect($this->generateUrl('mycategory_questiondisplay',
array('id' => $question->getId())));
}
}
return $this->render('MyCategoryBundle:Question:add.html.twig',
array(
'form' => $form->createView(),
));
}
My QuestionType form :
<?php
namespace My\CategoryBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class QuestionType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('description')
->add('answers', 'collection', array(
'type' => new AnswerType(),
'allow_add' => true)
);
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Iel\CategoryBundle\Entity\Question'
));
}
/**
* #return string
*/
public function getName()
{
return 'my_categorybundle_question';
}
}
My Question Entity :
<?php
namespace My\CategoryBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Question
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="My\CategoryBundle\Entity\QuestionRepository")
*/
class Question
{
/**
* #ORM\OneToMany(targetEntity="My\CategoryBundle\Entity\Answer",
mappedBy="question", cascade={"persist", "remove"})
*/
private $answers;
public function __construct()
{
$this->answers = new
\Doctrine\Common\Collections\ArrayCollection();
}
public function addAnswer(\My\CategoryBundle\Entity\Answer
$answer)
{
$this->answers[] = $answer;
$answers->setQuestion($this);
return $this;
}
public function removeAnswer(\My\CategoryBundle\Entity\Answer $answer)
{
$this->answers->removeElement($answer);
}
public function getAnswers()
{
return $this->answers;
}
public function setAnswers($answer)
{
$this->answer = $answer;
return $this;
}
/**
* #ORM\ManyToOne(targetEntity="My\CategoryBundle\Entity\Category",
inversedBy="question")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
* })
*/
private $category;
/**
* Set category
*
#param My\CategoryBundle\Entity\Category $category
*/
public function setCategory(\My\CategoryBundle\Entity\Category $category)
{
$this->category = $category;
}
/**
* Get category
*
#return My\CategoryBundle\Entity\Category
*/
public function getCategory()
{
return $this->category;
}
/**
* Remove categories
**
#param My\CategoryBundle\Entity\Category $categories
*/
public function removeCategory(\My\CategoryBundle\Entity\Category $category)
{
$this->categories->removeElement($category);
}
/**
* #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="text")
*/
private $description;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set titre
*
* #param string $titre
* #return Question
*/
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 Question
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
}
And finally, the Answer entity :
<?php
namespace My\CategoryBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Answer
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="My\CategoryBundle\Entity\AnswerRepository")
*/
class Answer
{
/**
* #ORM\ManyToOne(targetEntity="My\CategoryBundle\Entity\Question",
inversedBy="answer")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="question_id", referencedColumnName="id")
* })
*/
private $question;
/**
* Set question
*
#param My\CategoryBundle\Entity\Question $question
*/
public function setQuestion(\My\CategoryBundle\Entity\Question $question)
{
$this->question = $question;
}
/**
* Get question
*
#return My\CategoryBundle\Entity\Question
*/
public function getQuestion()
{
return $this->question;
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="answer", type="text", nullable=true)
*/
private $answer;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set answer
*
* #param string $answer
* #return Answer
*/
public function setAnswer($answer)
{
$this->answer = $answer;
return $this;
}
/**
* Get answer
*
* #return string
*/
public function getAnswer()
{
return $this->answer;
}
}
I'm really not able to find what's wrong in my form...
The problem is that your question does not have any answers yet. Hence no forms. Try
$question = new Question();
$question->addAnswer(new Answer());
That will show an empty answer form.
Look in the cookbook to see how to use javascript to add answers dynamically from within the browser.
I'm building a form generator using Symfony 2.2 with Doctrine. The base principle is that the user create a new form by filling its name and selecting the widgets he'd likes to have in a select menu.
We can think of WidgetInputText, WidgetSelect, WidgetFile, etc.
Here is an example of my model:
<?php
namespace Ineat\FormGeneratorBundle\Entity\Widget;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
/**
* Widget
*
* #ORM\Table(name="widget")
* #ORM\Entity
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="discr", type="string")
* #ORM\DiscriminatorMap({"widget_text" = "WidgetText", "widget_input_text" = "WidgetInputText", "widget_select" = "WidgetSelect"})
*/
abstract class Widget
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Form", inversedBy="widgets")
*/
private $form;
/**
* #var integer
*
* #ORM\OneToOne(targetEntity="Question")
*/
private $question;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set form
*
* #param \Ineat\FormGeneratorBundle\Entity\Form $form
* #return Widget
*/
public function setForm(\Ineat\FormGeneratorBundle\Entity\Form $form = null)
{
$this->form = $form;
return $this;
}
/**
* Get form
*
* #return \Ineat\FormGeneratorBundle\Entity\Form
*/
public function getForm()
{
return $this->form;
}
/**
* Set question
*
* #param \Ineat\FormGeneratorBundle\Entity\Question $question
* #return Widget
*/
public function setQuestion(\Ineat\FormGeneratorBundle\Entity\Question $question = null)
{
$this->question = $question;
return $this;
}
/**
* Get question
*
* #return \Ineat\FormGeneratorBundle\Entity\Question
*/
public function getQuestion()
{
return $this->question;
}
}
<?php
namespace Ineat\FormGeneratorBundle\Entity\Widget;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
/**
* Widget
*
* #ORM\Entity
* #ORM\Table(name="widget_text")
*/
class WidgetText extends Widget
{
/**
* #var string
*
* #ORM\Column(type="text")
*/
private $text;
/**
* Set text
*
* #param string $text
* #return WidgetText
*/
public function setText($text)
{
$this->text = $text;
return $this;
}
/**
* Get text
*
* #return string
*/
public function getText()
{
return $this->text;
}
}
<?php
namespace Ineat\FormGeneratorBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Form
*
* #ORM\Table(name="form")
* #ORM\Entity(repositoryClass="Ineat\FormGeneratorBundle\Entity\FormRepository")
* #UniqueEntity("name")
* #UniqueEntity("slug")
*/
class Form
{
/**
* #var integer
*
* #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 string
*
* #ORM\Column(name="slug", type="string", length=255)
*/
private $slug;
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="Widget", mappedBy="form", cascade={"persist"})
*/
private $widgets;
public function __construct()
{
$this->widgets = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Form
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set slug
*
* #param string $slug
* #return Form
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* Add widgets
*
* #param \Ineat\FormGeneratorBundle\Entity\Widget\Widget $widget
* #return Form
*/
public function addWidget(\Ineat\FormGeneratorBundle\Entity\Widget\Widget $widget)
{
$this->widgets[] = $widget;
return $this;
}
/**
* Remove widgets
*
* #param \Ineat\FormGeneratorBundle\Entity\Widget\Widget $widget
*/
public function removeWidget(\Ineat\FormGeneratorBundle\Entity\Widget\Widget $widget)
{
$this->widgets->removeElement($widget);
}
/**
* Get widgets
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getWidgets()
{
return $this->widgets;
}
/**
* Set widgets
*
* #param \Doctrine\Common\Collections\Collection $widgets
*/
public function setWidget(\Doctrine\Common\Collections\Collection $widgets)
{
$this->widgets = $widgets;
}
public function __set($name, $obj)
{
if (is_a($obj, '\Ineat\FormGeneratorBundle\Entity\Widget\Widget')) {
$this->addWidget($obj);
}
}
}
As you can see a form can have multiple widgets attached to him.
I've made an abstract class Widget because all widgets have common fields and are of type Widget and because in the Form entity it seems really really bad to had one collection per Widget type (bad and boring).
This model works, I've unit tested it and I'm able to attach a WidgetText to a form and then retrieve it.
The issue comes when I try to use forms with it.
<?php
namespace Ineat\FormGeneratorBundle\Form;
use Ineat\FormGeneratorBundle\Entity\Widget\WidgetText;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class FormType extends AbstractType
{
protected $widgets;
public function __construct(array $widgets = array())
{
$this->widgets = $widgets;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text')
->add('slug', 'text')
->add('WidgetText', 'collection', array(
'type' => new WidgetTextType(),
'allow_add' => true,
'attr' => array('class' => 'widget-text'),
'by_reference' => false
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Ineat\FormGeneratorBundle\Entity\Form',
));
}
public function getName()
{
return 'ineat_formgeneratorbundle_formtype';
}
}
<?php
namespace Ineat\FormGeneratorBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class WidgetTextType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('text', 'text')
;
}
public function getName()
{
return 'ineat_formgeneratorbundle_widgettexttype';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Ineat\FormGeneratorBundle\Entity\Widget\WidgetText',
));
}
}
When I try to display the form I've got the following error:
Neither property "WidgetText" nor method "getWidgetText()" nor method "isWidgetText()" exists in class "Ineat\FormGeneratorBundle\Entity\Form"
It's like Symfony doesn't know that my WidgetText is of type Widget too.
If in the controller (generated by Symfony) I change this line:
$this->createForm(new FormType(), new Form())
To:
$this->createForm(new FormType())
The form displays well but when submitting I've got no data binded.
I'm completly stuck there, from an OOP point of view I think this should work but I'm not sure if Symfony allows me to do what I want.
As mentioned in the comments of your question, you should change the name of the "WidgetText" field to "widgets". The reason behind that is that the names of the fields should match the accessors in your model (i.e. "name" for (set|get)Name(), "widgets" for (set|get)Widgets() etc.)
If you really want the name of a field to differ from the accessor in the model, you can also use the "property_path" option (which is set to the field's name by default):
$builder->add('WidgetText', ..., array(
...
'property_path' => 'widgets',
));
I have this entity (Registro):
<?php
namespace Gitek\RegistroBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Gitek\RegistroBundle\Entity\Registro
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Gitek\RegistroBundle\Entity\RegistroRepository"))
*/
class Registro
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var datetime $fecha
*
* #ORM\Column(name="fecha", type="datetime")
*/
private $fecha;
/**
* #var smallint $comenzado
*
* #ORM\Column(name="comenzado", type="smallint", nullable=true)
*/
private $comenzado;
/**
* #var smallint $completado
*
* #ORM\Column(name="completado", type="smallint", nullable=true)
*/
private $completado;
/**
* #var datetime $created_at
*
* #ORM\Column(name="created_at", type="datetime")
*/
private $created_at;
/**
* #var datetime $updated_at
*
* #ORM\Column(name="updated_at", type="datetime")
*/
private $updated_at;
/** #ORM\ManyToOne(targetEntity="Gitek\UsuarioBundle\Entity\Usuario") */
protected $usuario;
/** #ORM\ManyToOne(targetEntity="Gitek\HotelBundle\Entity\Tipotarea") */
protected $tipotarea;
/** #ORM\ManyToOne(targetEntity="Gitek\HotelBundle\Entity\Habitacion") */
protected $habitacion;
/** #ORM\ManyToOne(targetEntity="Gitek\RegistroBundle\Entity\Master") */
protected $master;
/**
* #ORM\ManyToMany(targetEntity="Gitek\HotelBundle\Entity\Incidencia", inversedBy="registros")
* #ORM\JoinTable(name="incidencia_registro",
* joinColumns={#ORM\JoinColumn(name="registro_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="incidencia_id", referencedColumnName="id")}
* )
*/
protected $incidencias;
public function __construct()
{
$this->created_at = new \DateTime();
$this->updated_at = new \DateTime();
}
// public function __toString()
// {
// return $this->getNombre();
// }
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set fecha
*
* #param datetime $fecha
*/
public function setFecha($fecha)
{
$this->fecha = $fecha;
}
/**
* Get fecha
*
* #return datetime
*/
public function getFecha()
{
return $this->fecha;
}
/**
* Set comenzado
*
* #param smallint $comenzado
*/
public function setComenzado($comenzado)
{
$this->comenzado = $comenzado;
}
/**
* Get comenzado
*
* #return smallint
*/
public function getComenzado()
{
return $this->comenzado;
}
/**
* Set completado
*
* #param smallint $completado
*/
public function setCompletado($completado)
{
$this->completado = $completado;
}
/**
* Get completado
*
* #return smallint
*/
public function getCompletado()
{
return $this->completado;
}
/**
* Set created_at
*
* #param datetime $createdAt
*/
public function setCreatedAt($createdAt)
{
$this->created_at = $createdAt;
}
/**
* Get created_at
*
* #return datetime
*/
public function getCreatedAt()
{
return $this->created_at;
}
/**
* Set updated_at
*
* #param datetime $updatedAt
*/
public function setUpdatedAt($updatedAt)
{
$this->updated_at = $updatedAt;
}
/**
* Get updated_at
*
* #return datetime
*/
public function getUpdatedAt()
{
return $this->updated_at;
}
/**
* Set usuario
*
* #param Gitek\UsuarioBundle\Entity\Usuario $usuario
*/
public function setUsuario(\Gitek\UsuarioBundle\Entity\Usuario $usuario)
{
$this->usuario = $usuario;
}
/**
* Get usuario
*
* #return Gitek\UsuarioBundle\Entity\Usuario
*/
public function getUsuario()
{
return $this->usuario;
}
/**
* Set tipotarea
*
* #param Gitek\HotelBundle\Entity\Tipotarea $tipotarea
*/
public function setTipotarea(\Gitek\HotelBundle\Entity\Tipotarea $tipotarea)
{
$this->tipotarea = $tipotarea;
}
/**
* Get tipotarea
*
* #return Gitek\HotelBundle\Entity\Tipotarea
*/
public function getTipotarea()
{
return $this->tipotarea;
}
/**
* Set habitacion
*
* #param Gitek\HotelBundle\Entity\Habitacion $habitacion
*/
public function setHabitacion(\Gitek\HotelBundle\Entity\Habitacion $habitacion)
{
$this->habitacion = $habitacion;
}
/**
* Get habitacion
*
* #return Gitek\HotelBundle\Entity\Habitacion
*/
public function getHabitacion()
{
return $this->habitacion;
}
/**
* Add incidencias
*
* #param Gitek\HotelBundle\Entity\Incidencia $incidencias
*/
public function addIncidencia(\Gitek\HotelBundle\Entity\Incidencia $incidencias)
{
$this->incidencias[] = $incidencias;
}
/**
* Get incidencias
*
* #return Doctrine\Common\Collections\Collection
*/
public function getIncidencias()
{
return $this->incidencias;
}
}
I wanted to save multiple data on a row, so I created a new Entity with only an array propery like this (Master):
<?php
namespace Gitek\RegistroBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
class Master
{
/** #ORM\OneToMany(targetEntity="Gitek\HotelBundle\Entity\Habitacion", mappedBy="master") */
protected $registros;
public function __construct()
{
$this->registros = new ArrayCollection();
}
public function getRegistros()
{
return $this->registros;
}
public function setRegistros(ArrayCollection $registros)
{
$this->registros = $registros;
}
}
I created my MasterType like this:
<?php
namespace Gitek\RegistroBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Doctrine\ORM\EntityRepository;
class MasterType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('registros', 'collection', array(
'type' => new RegistroType(),
'allow_add' => true,
'by_reference' => true,
));
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'Gitek\RegistroBundle\Entity\Master'
);
}
public function getName()
{
return 'master';
}
}
And this is my controller:
public function asignarAction()
{
$master = new Master();
$request = $this->getRequest();
$form = $this->createForm(new MasterType(), $master);
if ('POST' === $request->getMethod()) {
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($master);
$em->flush();
return $this->redirect($this->generateUrl('recepcion_asignar'));
}else {
print_r("ezez");
print_r($form->getErrors());
}
} else {
}
return $this->render('RegistroBundle:Recepcion:asignar.html.twig', array(
'registro' => $master,
'form' => $form->createView()
));
}
The form works ok, and I see the data is submited correctly but it is not persisted, I´m getting this error all the time:
Class Gitek\RegistroBundle\Entity\Master is not a valid entity or mapped super class.
I think that the problem is within de Master entity.
Any help or clue?
You missed the #Entity annotation on your Master class, you will also need a master table on your database for this to work.
If you don't want to create the master table, then you can skip the #Entity annotation, but you can not persist master. Instead you would have to iterate through the collection and persist only the entities in the array.