Symfony2 form - Remove related entity form on submit - php

I have an inherited entity CalendarMeeting from CalendarEvent that adds two related entities. One of which is an Address entity. When the CalendarMeetingis submitted I want to check if the Address form is empty, and if so, remove the form so that no Address is saved to the database. My code is as follows:
CalendarMeeting:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping AS ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity(repositoryClass="AppBundle\Entity\CalendarMeetingRepository")
* #ORM\Table(name="calendar_meetings")
*/
class CalendarMeeting extends CalendarEvent
{
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Address", cascade={"persist"})
* #ORM\JoinColumn(name="address_id", referencedColumnName="id")
*/
private $address;
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\User")
* #ORM\JoinTable(
* name="User2CalendarMeeting",
* joinColumns={#ORM\JoinColumn(name="calendar_meeting_id", referencedColumnName="id", nullable=false)},
* inverseJoinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)}
* )
*/
private $users;
/**
* #return mixed
*/
public function getAddress()
{
return $this->address;
}
/**
* #param mixed $address
* #return CalendarMeeting
*/
public function setAddress($address)
{
$this->address = $address;
return $this;
}
/**
* #return ArrayCollection
*/
public function getUsers()
{
return $this->users;
}
/**
* #param User $user
* #return void
*/
public function addUser(User $user)
{
$this->users->add($user);
}
/**
* #param User $user
* #return void
*/
public function removeUser(User $user)
{
$this->users->removeElement($user);
}
}
The Address entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping AS ORM;
/**
* #ORM\Entity(repositoryClass="AppBundle\Entity\AddressRepository")
* #ORM\Table(name="addresses")
* #ORM\HasLifecycleCallbacks
*/
class Address
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $name;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $address_1;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $address_2;
/**
* #ORM\Column(type="integer", nullable=true)
*/
private $postal_code;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $postal_address;
/**
* #ORM\Column(type="decimal", nullable=true, precision=10, scale=6)
*/
private $latitude;
/**
* #ORM\Column(type="decimal", nullable=true, precision=11, scale=6)
*/
private $longitude;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
private $created;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
private $updated;
/**
* #return mixed
*/
public function getId() {
return $this->id;
}
/**
* #return mixed
*/
public function getName() {
return $this->name;
}
/**
* #param mixed $name
* #return Address
*/
public function setName($name) {
$this->name = $name;
return $this;
}
/**
* #return mixed
*/
public function getAddress1() {
return $this->address_1;
}
/**
* #param mixed $address_1
* #return Address
*/
public function setAddress1($address_1) {
$this->address_1 = $address_1;
return $this;
}
/**
* #return mixed
*/
public function getAddress2() {
return $this->address_2;
}
/**
* #param mixed $address_2
* #return Address
*/
public function setAddress2($address_2) {
$this->address_2 = $address_2;
return $this;
}
/**
* #return mixed
*/
public function getPostalCode() {
return $this->postal_code;
}
/**
* #param mixed $postal_code
* #return Address
*/
public function setPostalCode($postal_code) {
$this->postal_code = $postal_code;
return $this;
}
/**
* #return mixed
*/
public function getPostalAddress() {
return $this->postal_address;
}
/**
* #param mixed $postal_address
* #return Address
*/
public function setPostalAddress($postal_address) {
$this->postal_address = $postal_address;
return $this;
}
/**
* #return mixed
*/
public function getLatitude() {
return $this->latitude;
}
/**
* #param mixed $latitude
* #return Address
*/
public function setLatitude($latitude) {
$this->latitude = $latitude;
return $this;
}
/**
* #return mixed
*/
public function getLongitude() {
return $this->longitude;
}
/**
* #param mixed $longitude
* #return Address
*/
public function setLongitude($longitude) {
$this->longitude = $longitude;
return $this;
}
/**
* #return mixed
*/
public function getCreated()
{
return $this->created;
}
/**
* #param \DateTime $created
* #return Address
*/
public function setCreated(\DateTime $created)
{
$this->created = $created;
return $this;
}
/**
* #return mixed
*/
public function getUpdated()
{
return $this->updated;
}
/**
* #param mixed $updated
* #return ShiftChange
*/
public function setUpdated(\DateTime $updated)
{
$this->updated = $updated;
return $this;
}
/**
* #ORM\PrePersist
* #ORM\PreUpdate
*/
public function updateTimestamps()
{
$this->setUpdated(new \DateTime('now'));
if ($this->getCreated() === null) {
$this->setCreated(new \DateTime('now'));
}
}
}
There is no CalendarMeetingType just the inherited CalendarEventType where I check what entity type is edited by using event listeners. It looks like this:
<?php
namespace AppBundle\Form;
use AppBundle\Entity\CalendarMeeting;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
class CalendarEventType extends AbstractType
{
protected $start = false;
protected $end = false;
public function __construct($date = null)
{
if ($date) {
$this->start = new \DateTime($date . ' 09:00:00');
$this->end = new \DateTime($date . ' 10:00:00');
}
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', null, array(
'attr' => array(
'placeholder' => 'app.forms.calendar.name',
),
'label' => 'app.forms.calendar.name',
'translation_domain' => 'AppBundle'
))
->add('description', null, array(
'label' => 'app.forms.calendar.description',
'translation_domain' => 'AppBundle'
))
->add('event_type', 'choice', array(
'label' => "app.forms.calendar.event_type.label",
'choices' => array(
'event' => 'app.forms.calendar.event_type.event',
'meeting' => 'app.forms.calendar.event_type.meeting',
'holiday' => 'app.forms.calendar.event_type.holiday',
),
'required' => true,
'expanded' => false,
'multiple' => false,
'mapped' => false,
'translation_domain' => 'AppBundle'
));
if ($this->start && $this->end) {
$builder
->add('start', 'datetime', array(
'date_widget' => 'single_text',
'time_widget' => 'text',
'data' => $this->start,
'label' => 'app.forms.calendar.start',
'translation_domain' => 'AppBundle',
))
->add('end', 'datetime', array(
'date_widget' => 'single_text',
'time_widget' => 'text',
'data' => $this->end,
'label' => 'app.forms.calendar.end',
'translation_domain' => 'AppBundle'
));
} else {
$builder
->add('start', 'datetime', array(
'date_widget' => 'single_text',
'time_widget' => 'text',
'label' => 'app.forms.calendar.start',
'translation_domain' => 'AppBundle',
))
->add('end', 'datetime', array(
'date_widget' => 'single_text',
'time_widget' => 'text',
'label' => 'app.forms.calendar.end',
'translation_domain' => 'AppBundle'
));
}
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
array($this, 'onPreSetData')
);
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
array($this, 'onPreSubmit')
);
}
/**
* #param \Symfony\Component\Form\FormEvent $event
*/
public function onPreSetData(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
/* Check we're looking at the right data/form */
if ($data instanceof CalendarMeeting) {
$form->add('address', new AddressType());
}
}
/**
* #param \Symfony\Component\Form\FormEvent $event
*/
public function onPreSubmit(FormEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
if ($data instanceof CalendarMeeting) {
if ($data->getAddress()->getAddress1() == "") {
$form->remove('address');
}
}
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\CalendarEvent'
));
}
/**
* #return string
*/
public function getName()
{
return 'appbundle_calendarevent';
}
}
The onPreSubmit function is not working obviously, but alas, this is what I hoped was the right way to do it. I can not figure out how to solve this (another way).
What happens now is that when I submit the form without any data in the address form fields, the address is saved to the database only with empty values. How can I stop the address in getting saved?
Thank you very much for your time.
Regards,
Tommy

I figured this out. I was going about it completely wrong. The solution was to add onDelete="CASCADE" on the CalendarMeeting address:
(edit: The onDelete="CASCADE" was removed from the join column as it was not needed)
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Address", cascade={"persist"})
* #ORM\JoinColumn(name="address_id", referencedColumnName="id", nullable=true)
*/
private $address;
And on the setAddress function, initially set the address parameter to null:
/**
* #param Address $address
* #return CalendarMeeting
*/
public function setAddress(Address $address = null)
{
$this->address = $address;
return $this;
}
Then on the CalendarEventType I changed adding the address type to the following so it accepts null:
if ($data instanceof CalendarMeeting) {
$form->add('address', new AddressType(), array(
'required' => false,
));
}
Finally in the CalendarEventController, I check if the address fields contains any values. If not, set the address to null:
// Check if calendar meeting
if($entity instanceof CalendarMeeting) {
$address_form = $editForm->get('address')->getData();
if($address_form === null ||
($address_form->getName() === null &&
$address_form->getAddress1() === null &&
$address_form->getPostalCode() === null &&
$address_form->getPostalAddress() == null)
) {
$entity->setAddress(null);
}
}
$em->flush();
return ...redirect...
If anyone has a better solution, please post an answer, and I will accept it. Also, please comment if this is a dirty solution. I have a feeling it is.. :)

Related

Symfony - Error upon adding another DateType::class, array('widget' => 'single_text')

See I have 3 datetime type entity in my User.php
<?php
namespace UserBundle\Entity;
use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="first_name", type="string", length=255, nullable=true)
*/
protected $firstName;
/**
* #ORM\Column(name="middle_name", type="string", length=255, nullable=true)
*/
protected $middleName;
/**
* #ORM\Column(name="last_name", type="string", length=255, nullable=true)
*/
protected $lastName;
/**
* #ORM\Column(name="position", type="string", length=255, nullable=true)
*/
protected $position;
/**
* #ORM\Column(name="gender", type="string", length=255, nullable=true)
*/
protected $gender;
/**
* #ORM\Column(name="birth_date", type="datetime", nullable=true)
*/
protected $birthDate;
/**
* #ORM\Column(name="address", type="string", length=255, nullable=true)
*/
protected $address;
/**
* #ORM\Column(name="school", type="string", length=255, nullable=true)
*/
protected $school;
/**
* #ORM\Column(name="hired_date", type="datetime", nullable=true)
*/
protected $hiredDate;
/**
* #ORM\Column(name="end_date", type="datetime", nullable=true)
*/
protected $endDate;
// Change the targetEntity path if you want to create the group
/**
* #ORM\ManyToMany(targetEntity="UserBundle\Entity\Group")
* #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;
public function __construct()
{
parent::__construct();
}
/**
* #return String
*/
public function getFirstName()
{
return $this->firstName;
}
/**
* #return String
*/
public function getMiddleName()
{
return $this->middleName;
}
/**
* #return String
*/
public function getLastName()
{
return $this->lastName;
}
/**
* #return String
*/
public function getPosition()
{
return $this->position;
}
/**
* #return String
*/
public function getGender()
{
return $this->gender;
}
/**
* #return String
*/
public function getBirthDate()
{
return $this->birthDate;
}
/**
* #return String
*/
public function getAddress()
{
return $this->address;
}
/**
* #return String
*/
public function getSchool()
{
return $this->school;
}
/**
* #return String
*/
public function getHiredDate()
{
return $this->hiredDate;
}
/**
* #return String
*/
public function getEndDate()
{
return $this->endDate;
}
/**
* #param String $firstName
* #return User
*/
public function setFirstName($firstName)
{
$this->firstName = $firstName;
return $this;
}
/**
* #param String $middleName
* #return User
*/
public function setMiddleName($middleName)
{
$this->middleName = $middleName;
return $this;
}
/**
* #param String $lastName
* #return User
*/
public function setLastName($lastName)
{
$this->lastName = $lastName;
return $this;
}
/**
* #param String $position
* #return User
*/
public function setPosition($position)
{
$this->position = $position;
return $this;
}
/**
* #param String $gender
* #return User
*/
public function setGender($gender)
{
$this->gender = $gender;
return $this;
}
/**
* #param String $birthDate
* #return User
*/
public function setBirthDate($birthDate)
{
$this->birthDate = $birthDate;
return $this;
}
/**
* #param String $address
* #return User
*/
public function setAddress($address)
{
$this->address = $address;
return $this;
}
/**
* #param String $school
* #return User
*/
public function setSchool($school)
{
$this->school = $school;
return $this;
}
/**
* #param String $hiredDate
* #return User
*/
public function setHiredDate($hiredDate)
{
$this->hiredDate = $hiredDate;
return $this;
}
/**
* #param String $endDate
* #return User
*/
public function setEndDate($endDate)
{
$this->endDate = $endDate;
return $this;
}
}
The problem is when I try to add these dates in my ProfileFormType.php, only the birthDate is added as a widget but the other two dates(hiredDate & endDate) are throwing this error.
Unable to transform value for property path "hiredDate": datefmt_format: invalid PHP type for date: U_ILLEGAL_ARGUMENT_ERROR
the same with endDate after birthdate
Unable to transform value for property path "endDate": datefmt_format: invalid PHP type for date: U_ILLEGAL_ARGUMENT_ERROR
This is my ProfileFormType.php
<?php
namespace UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\DateType;
class ProfileFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstName', 'text', array('label' => 'form.firstName', 'translation_domain' => 'FOSUserBundle'))
->add('middleName', 'text', array('label' => 'form.middleName', 'translation_domain' => 'FOSUserBundle'))
->add('lastName', 'text', array('label' => 'form.lastName', 'translation_domain' => 'FOSUserBundle'))
->add('position', 'text', array('label' => 'form.position', 'translation_domain' => 'FOSUserBundle'))
->add('gender', 'text', array('label' => 'form.gender', 'translation_domain' => 'FOSUserBundle'))
->add('address', 'text', array('label' => 'form.address', 'translation_domain' => 'FOSUserBundle'))
->add('school', 'text', array('label' => 'form.school', 'translation_domain' => 'FOSUserBundle'))
->add('birthDate', DateType::class, array(
'widget' => 'single_text',
'label' => 'form.birthDate',
'translation_domain' => 'FOSUserBundle'
))
->add('hiredDate', DateType::class, array(
'widget' => 'single_text',
'label' => 'form.hiredDate',
'translation_domain' => 'FOSUserBundle'
))
->add('endDate', DateType::class, array(
'widget' => 'single_text',
'label' => 'form.endDate',
'translation_domain' => 'FOSUserBundle'
))
;
}
public function getParent()
{
return 'fos_user_profile';
}
public function getName()
{
return 'user_profile';
}
}
Kindly help me what's wrong with my code?

Catchable Fatal Error: Invalid argument passed to method, expected some time and null given

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());
}
);

Symfony entity property not updating

I have a small questuion.
I have a article with repeatable property tags. When i editing exist article and add new tags all is ok. But if a remove tag from form in article this tag still exists.
As i understand post data binding to the form and to the entity. Thats way new tags appear in the material.
But why did they not disappear after binding new post data ?
public function editAction(Article $article, Request $request)
{
// The second parameter is used to specify on what object the role is tested.
if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
return $this->redirectToRoute('login');
}
// update Article modify date
$article->setModifyDate(new \DateTime());
// create form
$form = $this->createForm(ArticleType::class, $article, [
'manager' => $this->getDoctrine()->getManager()
]);
$form->handleRequest($request);
//print_r($article->getTags()); Deleted tag still here
UPDATE
Here is my Article entity
**
* Class Article
* #package BackendBundle\Entity
* #ORM\Table(name="articles")
* #ORM\Entity(repositoryClass="BackendBundle\Entity\ArticleRepository")
*/
class Article
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=255, unique=true)
* #Assert\NotBlank()
*/
private $name;
/**
* #ORM\Column(type="string", length=60, unique=true)
* #Assert\NotBlank()
*/
private $alias;
/**
* #ORM\Column(type="text")
* #Assert\NotBlank()
*/
private $content;
/**
* #ORM\Column(type="integer", length=255)
* #Assert\NotBlank()
*/
private $author;
/**
* #ORM\Column(type="datetime")
* #Assert\NotBlank()
*/
private $publishDate;
/**
* #ORM\Column(type="datetime")
* #Assert\NotBlank()
*/
private $modifyDate;
/**
* #ORM\ManyToMany(targetEntity="Tag", inversedBy="articles", cascade={"persist","remove"})
* #ORM\JoinTable(
* name="articles_tags",
* joinColumns={#ORM\JoinColumn(name="article_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="tag_id", referencedColumnName="id")})
*/
private $tags;
/**
* Article constructor.
*/
public function __construct()
{
$this->tags = new ArrayCollection();
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set article name.
*
* #param string $name
*
* #return $this
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Return article name.
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set articles alias.
*
* #param string $alias
*
* #return $this
*/
public function setAlias($alias)
{
$this->alias = $alias;
return $this;
}
/**
* Returns article alias.
* #return mixed
*/
public function getAlias()
{
return $this->alias;
}
/**
* Set article content.
*
* #param string $content
*
* #return $this
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Return article content
* #return string
*/
public function getContent()
{
return $this->content;
}
/**
* Set article author
*
* #param integer $author ID of author
*
* #return mixed
*/
public function setAuthor($author)
{
$this->author = $author;
return $this;
}
/**
* Return author id.
* #return int Id of the author.
*/
public function getAuthor()
{
return $this->author;
}
/**
* Set article publish date.
*
* #param string $date
*
* #return $this
*/
public function setPublishDate($date)
{
$this->publishDate = $date;
return $this;
}
/**
* Return article publish date.
* #return string
*/
public function getPublishDate()
{
return $this->publishDate;
}
/**
* Set article modify date
*
* #param string $date
*
* #return $this
*/
public function setModifyDate($date)
{
$this->modifyDate = $date;
return $this;
}
/**
* Return article modify date
* #return string
*/
public function getModifyDate()
{
return $this->modifyDate;
}
/**
* Set tags for article.
*
* #param ArrayCollection|array $tags
*
* #return $this
*/
public function setTags($tags)
{
if (!empty($tags))
{
foreach ($tags as $tag)
{
$this->setTag($tag);
}
}
return $this;
}
/**
* Set article tag.
*
* #param Tag $tag
*
* #return $this
*
*/
public function setTag(Tag $tag)
{
if (!$this->tags->contains($tag))
{
$this->tags->set($tag->getName(), $tag);
$tag->setArticle($this);
}
return $this;
}
/**
* Remove all tags from article.
*/
public function removeTags()
{
if(!empty($this->tags))
{
foreach($this->tags as $tag)
{
$this->removeTag($tag);
}
}
return $this;
}
/**
* #param \BackendBundle\Entity\Tag $tag
*
* #return $this
*/
public function removeTag(Tag $tag)
{
if ($this->tags->contains($tag))
{
$this->tags->removeElement($tag);
$tag->removeArticle($this);
}
return $this;
}
/**
* Returns all tags for article.
* #return ArrayCollection
*/
public function getTags()
{
return $this->tags;
}
}
And ArticleType
/**
* Class ArticleType
* #package AppBundle\Form
*/
class ArticleType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$tagTransformer = new TagTransformer($options['manager']);
$builder
->add('name', TextType::class, array(
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control'),
'label' => 'article.name'
))
->add('alias', TextType::class, array(
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control'),
'label' => 'article.alias'
))
->add('content', TextareaType::class, array(
'label_attr' => array('class' => ''),
'attr' => array(
'class' => 'form-control'
),
'label' => 'article.content'
))
->add('publish_date', DateType::class, array(
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control'),
'format' => 'dd-MM-yyyy',
'label' => 'article.publish_date'
))
->add('modify_date', DateType::class, array(
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control'),
'format' => 'dd-MM-yyyy',
'label' => 'article.modify_date'
))
->add($builder->create('tags', CollectionType::class, array(
'label' => 'article.tags',
'by_reference' => false,
'allow_add' => true,
'allow_delete' => true,
))->addViewTransformer($tagTransformer));
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'BackendBundle\Entity\Article',
));
$resolver->setRequired(array(
'manager',
));
$resolver->setAllowedTypes('manager', 'Doctrine\Common\Persistence\ObjectManager');
}
}
Try to modify add tag and remove tag function in Article entity to something like this
public function addTag(Tag $tag)
{
$this->tags[] = $tag;
$tag->addArticle($this);
return $this;
}
public function removeTag(Tag $tag)
{
$this->tags->removeElement($tag);
$tag->removeArticle($this);
}

Symfony2 Embed a Collection of Forms

Hi i have problem with form embeded.
I have 3 class with relation OneToMany
StockTaking OneToMany StockTakingDetail ManyToOne Hardware
Wheh i submit the form i get error.
I dont know where I made a mistake.
Error:
Catchable Fatal Error: Argument 1 passed to
AppBundle\Entity\MagazineStockTakingDetails::setHardware() must be an
instance of AppBundle\Entity\Hardware, array given, called in
C:\Projekty\sla\vendor\symfony\symfony\src\Symfony\Component\PropertyAccess\PropertyAccessor.php
on line 442 and defined
Below i past code my class and form. Please help me find mistake.
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Class MagazineStockTaking
* #package AppBundle\Entity
* #ORM\Entity()
* #ORM\Table(name="sla_stocktaking")
*/
class MagazineStockTaking
{
/**
* #ORM\Id
* #ORM\Column(name="stockTakingId", type="integer", nullable=false)
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="stockinNumber", type="string", length=20, nullable=false)
*/
protected $stockingnumber;
/**
* #ORM\Column(name="stockinDate", type="datetime", nullable=false)
*/
protected $stockingdate;
/**
* #ORM\Column(name="stockingNote", type="string", length=1000, nullable=false)
*/
protected $stockingnote;
////////////////////////////////////////////////
// RELACJE
////////////////////////////////////////////////
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Magazine", inversedBy="stocktaking")
* #ORM\JoinColumn(name="magazine_id", referencedColumnName="magazineId", nullable=false)
*/
protected $magazine;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="stocktaking")
* #ORM\JoinColumn(name="user_id", referencedColumnName="userId", nullable=false)
*/
protected $user;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\MagazineStockTakingDetails", mappedBy="stocktaking", cascade={"persist"})
*/
protected $details;
////////////////////////////////////////////////
// GET SET
////////////////////////////////////////////////
/**
* Constructor
*/
public function __construct()
{
$this->details = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set stockingnumber
*
* #param string $stockingnumber
* #return MagazineStockTaking
*/
public function setStockingnumber($stockingnumber)
{
$this->stockingnumber = $stockingnumber;
return $this;
}
/**
* Get stockingnumber
*
* #return string
*/
public function getStockingnumber()
{
return $this->stockingnumber;
}
/**
* Set stockingdate
*
* #param \DateTime $stockingdate
* #return MagazineStockTaking
*/
public function setStockingdate($stockingdate)
{
$this->stockingdate = $stockingdate;
return $this;
}
/**
* Get stockingdate
*
* #return \DateTime
*/
public function getStockingdate()
{
return $this->stockingdate;
}
/**
* Set stockingnote
*
* #param string $stockingnote
* #return MagazineStockTaking
*/
public function setStockingnote($stockingnote)
{
$this->stockingnote = $stockingnote;
return $this;
}
/**
* Get stockingnote
*
* #return string
*/
public function getStockingnote()
{
return $this->stockingnote;
}
/**
* Set magazine
*
* #param \AppBundle\Entity\Magazine $magazine
* #return MagazineStockTaking
*/
public function setMagazine(\AppBundle\Entity\Magazine $magazine)
{
$this->magazine = $magazine;
return $this;
}
/**
* Get magazine
*
* #return \AppBundle\Entity\Magazine
*/
public function getMagazine()
{
return $this->magazine;
}
/**
* Set user
*
* #param \AppBundle\Entity\User $user
* #return MagazineStockTaking
*/
public function setUser(\AppBundle\Entity\User $user)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \AppBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* Add details
*
* #param \AppBundle\Entity\MagazineStockTakingDetails $details
* #return MagazineStockTaking
*/
public function addDetail(\AppBundle\Entity\MagazineStockTakingDetails $details)
{
$this->details[] = $details;
return $this;
}
/**
* Remove details
*
* #param \AppBundle\Entity\MagazineStockTakingDetails $details
*/
public function removeDetail(\AppBundle\Entity\MagazineStockTakingDetails $details)
{
$this->details->removeElement($details);
}
/**
* Get details
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getDetails()
{
return $this->details;
}
}
Second Class
<?php
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Class MagazineStockTakingDetails
* #package AppBundle\Entity
* #ORM\Entity()
* #ORM\Table(name="sla_stocktakingdetails")
*/
class MagazineStockTakingDetails
{
/**
* #ORM\Id()
* #ORM\Column(name="stackTakingDetailsId", type="integer", nullable=false)
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="hardwareCount", type="integer", nullable=false)
*/
protected $count = 1;
/////////////////////////////////////////////
// RELACJE
/////////////////////////////////////////////
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\MagazineStockTaking", inversedBy="details")
* #ORM\JoinColumn(name="stacktaking_id", referencedColumnName="stockTakingId", nullable=false)
*/
protected $stocktaking;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Hardware", inversedBy="stocktakingdetails",cascade={"persist"})
* #ORM\JoinColumn(name="hardware_id", referencedColumnName="hardwareId", nullable=false)
*/
protected $hardware;
/////////////////////////////////////////////
// GET SET
/////////////////////////////////////////////
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set count
*
* #param integer $count
* #return MagazineStockTakingDetails
*/
public function setCount($count)
{
$this->count = $count;
return $this;
}
/**
* Get count
*
* #return integer
*/
public function getCount()
{
return $this->count;
}
/**
* Set stocktaking
*
* #param \AppBundle\Entity\MagazineStockTaking $stocktaking
* #return MagazineStockTakingDetails
*/
public function setStocktaking(\AppBundle\Entity\MagazineStockTaking $stocktaking)
{
$this->stocktaking = $stocktaking;
return $this;
}
/**
* Get stocktaking
*
* #return \AppBundle\Entity\MagazineStockTaking
*/
public function getStocktaking()
{
return $this->stocktaking;
}
/**
* Set hardware
*
* #param \AppBundle\Entity\Hardware $hardware
* #return MagazineStockTakingDetails
*/
public function setHardware(\AppBundle\Entity\Hardware $hardware)
{
$this->hardware = $hardware;
return $this;
}
/**
* Get hardware
*
* #return \AppBundle\Entity\Hardware
*/
public function getHardware()
{
return $this->hardware;
}
}
Third Class
<?php
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;
use JMS\Serializer\Annotation\Groups;
/**
* Class Hardware
* #package AppBundle\Entity
* #ORM\Entity(repositoryClass="HardwareRepository", )
* #ORM\Table(name="sla_hardwares")
* #JMS\ExclusionPolicy("all")
*/
class Hardware
{
/**
* #ORM\Id()
* #ORM\Column(name="hardwareId", type="integer", nullable=false)
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="hardwareSn", type="string", length=200, nullable=true)
*/
protected $sn;
/**
* #ORM\Column(name="hardwareGwarantyDate", type="datetime", nullable=true)
*/
protected $gwarantydate;
/**
* #ORM\Column(name="hardwareNote", type="string", length=750, nullable=true)
*/
protected $note;
/**
* #ORM\Column(name="hardwareIsReturned", type="boolean", nullable=false)
*/
protected $isreturned = false;
////////////////////////////////////////
//// RELACJE
////////////////////////////////////////
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\HardwareProducent", inversedBy="hardware")
* #ORM\JoinColumn(name="producent_id", referencedColumnName="producentId", nullable=false)
*/
protected $producent;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\HardwareCategory", inversedBy="hardware")
* #ORM\JoinColumn(name="category_id", referencedColumnName="hardwareCategoryId", nullable=false)
*/
protected $category;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\HardwareModel", inversedBy="hardware")
* #ORM\JoinColumn(name="model_id", referencedColumnName="hardwareModelId", nullable=false)
*/
protected $model;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\HardwareStatus", inversedBy="hardware")
* #ORM\JoinColumn(name="status_id", referencedColumnName="statusId", nullable=false)
*/
protected $status;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\HardwareStatusHistory", mappedBy="hardware")
*/
protected $statushistory;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\MagazineDetails", mappedBy="hardware")
*/
protected $magazine;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\MagazineShiftDetails", mappedBy="hardware")
*/
protected $magazineshift;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\MagazineUtilizeDetails", mappedBy="hardware")
*/
protected $utilize;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\MagazineStockTakingDetails", mappedBy="hardware", cascade={"persist"})
*/
protected $stocktakingdetails;
////////////////////////////////////////
//// GET SET
////////////////////////////////////////
/**
* Constructor
*/
public function __construct()
{
$this->statushistory = new \Doctrine\Common\Collections\ArrayCollection();
$this->magazine = new \Doctrine\Common\Collections\ArrayCollection();
$this->magazineshift = new \Doctrine\Common\Collections\ArrayCollection();
$this->utilize = new \Doctrine\Common\Collections\ArrayCollection();
$this->stocktakingdetails = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set sn
*
* #param string $sn
* #return Hardware
*/
public function setSn($sn)
{
$this->sn = $sn;
return $this;
}
/**
* Get sn
*
* #return string
*/
public function getSn()
{
return $this->sn;
}
/**
* Set gwarantydate
*
* #param \DateTime $gwarantydate
* #return Hardware
*/
public function setGwarantydate($gwarantydate)
{
$this->gwarantydate = $gwarantydate;
return $this;
}
/**
* Get gwarantydate
*
* #return \DateTime
*/
public function getGwarantydate()
{
return $this->gwarantydate;
}
/**
* Set note
*
* #param string $note
* #return Hardware
*/
public function setNote($note)
{
$this->note = $note;
return $this;
}
/**
* Get note
*
* #return string
*/
public function getNote()
{
return $this->note;
}
/**
* Set isreturned
*
* #param boolean $isreturned
* #return Hardware
*/
public function setIsreturned($isreturned)
{
$this->isreturned = $isreturned;
return $this;
}
/**
* Get isreturned
*
* #return boolean
*/
public function getIsreturned()
{
return $this->isreturned;
}
/**
* Set producent
*
* #param \AppBundle\Entity\HardwareProducent $producent
* #return Hardware
*/
public function setProducent(\AppBundle\Entity\HardwareProducent $producent)
{
$this->producent = $producent;
return $this;
}
/**
* Get producent
*
* #return \AppBundle\Entity\HardwareProducent
*/
public function getProducent()
{
return $this->producent;
}
/**
* Set category
*
* #param \AppBundle\Entity\HardwareCategory $category
* #return Hardware
*/
public function setCategory(\AppBundle\Entity\HardwareCategory $category)
{
$this->category = $category;
return $this;
}
/**
* Get category
*
* #return \AppBundle\Entity\HardwareCategory
*/
public function getCategory()
{
return $this->category;
}
/**
* Set model
*
* #param \AppBundle\Entity\HardwareModel $model
* #return Hardware
*/
public function setModel(\AppBundle\Entity\HardwareModel $model)
{
$this->model = $model;
return $this;
}
/**
* Get model
*
* #return \AppBundle\Entity\HardwareModel
*/
public function getModel()
{
return $this->model;
}
/**
* Set status
*
* #param \AppBundle\Entity\HardwareStatus $status
* #return Hardware
*/
public function setStatus(\AppBundle\Entity\HardwareStatus $status)
{
$this->status = $status;
return $this;
}
/**
* Get status
*
* #return \AppBundle\Entity\HardwareStatus
*/
public function getStatus()
{
return $this->status;
}
/**
* Add statushistory
*
* #param \AppBundle\Entity\HardwareStatusHistory $statushistory
* #return Hardware
*/
public function addStatushistory(\AppBundle\Entity\HardwareStatusHistory $statushistory)
{
$this->statushistory[] = $statushistory;
return $this;
}
/**
* Remove statushistory
*
* #param \AppBundle\Entity\HardwareStatusHistory $statushistory
*/
public function removeStatushistory(\AppBundle\Entity\HardwareStatusHistory $statushistory)
{
$this->statushistory->removeElement($statushistory);
}
/**
* Get statushistory
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getStatushistory()
{
return $this->statushistory;
}
/**
* Add magazine
*
* #param \AppBundle\Entity\MagazineDetails $magazine
* #return Hardware
*/
public function addMagazine(\AppBundle\Entity\MagazineDetails $magazine)
{
$this->magazine[] = $magazine;
return $this;
}
/**
* Remove magazine
*
* #param \AppBundle\Entity\MagazineDetails $magazine
*/
public function removeMagazine(\AppBundle\Entity\MagazineDetails $magazine)
{
$this->magazine->removeElement($magazine);
}
/**
* Get magazine
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getMagazine()
{
return $this->magazine;
}
/**
* Add magazineshift
*
* #param \AppBundle\Entity\MagazineShiftDetails $magazineshift
* #return Hardware
*/
public function addMagazineshift(\AppBundle\Entity\MagazineShiftDetails $magazineshift)
{
$this->magazineshift[] = $magazineshift;
return $this;
}
/**
* Remove magazineshift
*
* #param \AppBundle\Entity\MagazineShiftDetails $magazineshift
*/
public function removeMagazineshift(\AppBundle\Entity\MagazineShiftDetails $magazineshift)
{
$this->magazineshift->removeElement($magazineshift);
}
/**
* Get magazineshift
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getMagazineshift()
{
return $this->magazineshift;
}
/**
* Add utilize
*
* #param \AppBundle\Entity\MagazineUtilizeDetails $utilize
* #return Hardware
*/
public function addUtilize(\AppBundle\Entity\MagazineUtilizeDetails $utilize)
{
$this->utilize[] = $utilize;
return $this;
}
/**
* Remove utilize
*
* #param \AppBundle\Entity\MagazineUtilizeDetails $utilize
*/
public function removeUtilize(\AppBundle\Entity\MagazineUtilizeDetails $utilize)
{
$this->utilize->removeElement($utilize);
}
/**
* Get utilize
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUtilize()
{
return $this->utilize;
}
/**
* Add stocktakingdetails
*
* #param \AppBundle\Entity\MagazineStockTakingDetails $stocktakingdetails
* #return Hardware
*/
public function addStocktakingdetail(\AppBundle\Entity\MagazineStockTakingDetails $stocktakingdetails)
{
$this->stocktakingdetails[] = $stocktakingdetails;
$stocktakingdetails->setHardware($this);
return $this;
}
/**
* Remove stocktakingdetails
*
* #param \AppBundle\Entity\MagazineStockTakingDetails $stocktakingdetails
*/
public function removeStocktakingdetail(\AppBundle\Entity\MagazineStockTakingDetails $stocktakingdetails)
{
$this->stocktakingdetails->removeElement($stocktakingdetails);
}
/**
* Get stocktakingdetails
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getStocktakingdetails()
{
return $this->stocktakingdetails;
}
}
First Form Class
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class StockTakingFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('stockingnote','textarea',array(
'label' => false,
'attr' => array(
'class' => 'gui-textarea',
'placeholder' => 'Uwagi',
'data-text' => 'Uwagi'
),
'required' => false
))
->add('details','collection',array(
'type' => new StockTakingDetailFormType(),
'allow_add' => true,
'by_reference' => false
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\MagazineStockTaking',
'attr' => array(
'id' => 'form_stoking'
)
));
}
public function getName() {
return 'stocktaking';
}
}
Second Form Class
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class StockTakingDetailFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('count','number',array(
'label' => false,
'data' => '1',
'required' => false
))
->add('hardware','collection',array(
'type' => new HardwareFormType(),
'allow_add' => true,
'by_reference' => false
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\MagazineStockTakingDetails'
));
}
public function getName()
{
return 'stocktakingtetail';
}
}
Third Form Class
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class HardwareFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('sn','text',array(
'label' => false,
'attr' => array(
'class' => 'gui-input',
'placeholder' => 'Numer Seryjny Urządzenia'
),
'required' => true
))
->add('gwarantydate','number',array(
'label' => false,
'attr' => array(
'class' => 'gui-input',
'placeholder' => 'Ilość Gwarancji (miesięcy)'
),
'required' => false
))
->add('isreturned','checkbox',array(
'label' => 'Sprzęt Rotacyjny',
'label_attr' => array(
'class' => 'option-primary'
),
'required' => true
))
->add('note','textarea' ,array(
'label' => false,
'attr' => array(
'class' => 'gui-textarea',
'placeholder' => 'Opis',
'data-text' => 'Opis'
),
'required' => false
))
->add('producent','entity',array(
'class' => 'AppBundle\Entity\HardwareProducent',
'property' => 'name',
'label' => false,
'attr' => array(
'class' => 'select',
'placeholder' => 'Producent'
),
'required' => true
))
->add('category','entity',array(
'class' => 'AppBundle\Entity\HardwareCategory',
'property' => 'name',
'label' => false,
'attr' => array(
'class' => 'select',
'placeholder' => 'Kategoria'
),
'required' => true
))
->add('model','entity',array(
'class' => 'AppBundle\Entity\HardwareModel',
'property' => 'name',
'label' => false,
'attr' => array(
'class' => 'select',
'placeholder' => 'Model'
),
'required' => true
))
->add('status','entity',array(
'class' => 'AppBundle\Entity\HardwareStatus',
'property' => 'name',
'label' => false,
'attr' => array(
'class' => 'select',
'placeholder' => 'Status'
),
'required' => true
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Hardware'
));
}
public function getName()
{
return 'hardware';
}
}
If you have a ManyToOne on the hardware the MagazineStockTakingDetails has a reference to an object of the type Hardware, therefore you can only set one object of the type hardware, but you are trying to set an ArrayCollection.
This can't work:
->add('hardware','collection',array(
'type' => new HardwareFormType(),
'allow_add' => true,
'by_reference' => false
))
You will need to do something like this:
->add('hardware', new HardwareFormType(),array(
...
))

How to update particular image related data using doctrine entity with one to many relationship in Symfony 2

I have two entities (namely Book, Image) having OneToMany relationship between them, i.e. One book can have more than one images.
Now when I am trying to edit the details of the book, how can I do edit for any particular image for that particular book?
More clearly if I say, I want to alter only one particular image out of all the images previously uploaded. Can anyone help me on this please?
Below are my entities and forms.
/**
* #ORM\Table(name="books")
* #ORM\HasLifecycleCallbacks
* #ORM\Entity(repositoryClass="Library\MainBundle\Entity\BookRepository")
*/
class Book
{
/**
* #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="subject", type="string", length=255)
*/
private $subject;
/**
* #var string
*
* #ORM\Column(name="isbn", type="string", length=255)
*/
private $isbn;
/**
* #var string
*
* #ORM\Column(name="Description", type="text")
*/
private $description;
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="books")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
**/
private $category;
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="bookpublishers")
* #ORM\JoinColumn(name="publisher_id", referencedColumnName="id")
**/
private $publisher;
/**
* #ORM\ManyToMany(targetEntity="User", inversedBy="bookauthors")
* #ORM\JoinTable(name="book_author")
**/
private $author;
/**
* #ORM\OneToMany(targetEntity="BookReview", mappedBy="bookreview", cascade={"all"})
**/
private $reviews;
/**
* #var string $image
* #Assert\File( maxSize = "1024k", mimeTypesMessage = "Please upload a valid Image")
* #ORM\Column(name="image", type="string", length=255)
*/
private $image;
/**
* #ORM\OneToMany(targetEntity="Image", mappedBy="book", cascade={"all"})
**/
private $pictures;
/**
* #var string
*/
private $imageName;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Book
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set subject
*
* #param string $subject
* #return Book
*/
public function setSubject($subject)
{
$this->subject = $subject;
return $this;
}
/**
* Get subject
*
* #return string
*/
public function getSubject()
{
return $this->subject;
}
/**
* Set isbn
*
* #param string $isbn
* #return Book
*/
public function setIsbn($isbn)
{
$this->isbn = $isbn;
return $this;
}
/**
* Get isbn
*
* #return string
*/
public function getIsbn()
{
return $this->isbn;
}
/**
* Set description
*
* #param string $description
* #return Book
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set category
*
* #param \Library\MainBundle\Entity\Category $category
* #return Book
*/
public function setCategory(Category $category = null)
{
$this->category = $category;
return $this;
}
/**
* Get category
*
* #return \Library\MainBundle\Entity\Category
*/
public function getCategory()
{
return $this->category;
}
/**
* Set publisher
*
* #param \Library\MainBundle\Entity\User $publisher
* #return Book
*/
public function setPublisher(User $publisher = null)
{
$this->publisher = $publisher;
return $this;
}
/**
* Get publisher
*
* #return \Library\MainBundle\Entity\User
*/
public function getPublisher()
{
return $this->publisher;
}
/**
* Add author
*
* #param \Library\MainBundle\Entity\User $author
* #return Book
*/
public function addAuthor(User $author)
{
$this->author[] = $author;
return $this;
}
/**
* Remove author
*
* #param \Library\MainBundle\Entity\User $author
*/
public function removeAuthor(User $author)
{
$this->author->removeElement($author);
}
/**
* Get author
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getAuthor()
{
return $this->author;
}
/**
* Set author
*
* #return User
*/
public function setAuthor(User $author)
{
$this->author[] = $author;
}
/**
* Add reviews
*
* #param \Library\MainBundle\Entity\BookReview $reviews
* #return Book
*/
public function addReview(BookReview $reviews)
{
$this->reviews[] = $reviews;
return $this;
}
/**
* Remove reviews
*
* #param \Library\MainBundle\Entity\BookReview $reviews
*/
public function removeReview(BookReview $reviews)
{
$this->reviews->removeElement($reviews);
}
/**
* Get reviews
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getReviews()
{
return $this->reviews;
}
public function getFullImagePath() {
return null === $this->image ? null : $this->getUploadRootDir(). $this->image;
}
protected function getUploadRootDir() {
// the absolute directory path where uploaded documents should be saved
return $this->getTmpUploadRootDir().$this->getId()."/";
}
protected function getTmpUploadRootDir() {
// the absolute directory path where uploaded documents should be saved
return __DIR__ . '/../../../../web/upload/books/';
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function uploadImage() {
// the file property can be empty if the field is not required
if (null === $this->image) {
return;
}
$tempImageName = time() . '_' .$this->image->getClientOriginalName();
if(!$this->id){
$this->setImageName($this->image->getClientOriginalName());
$this->image->move($this->getTmpUploadRootDir(), $this->image->getClientOriginalName());
}else{
$this->image->move($this->getUploadRootDir(), $tempImageName);
unlink($this->getUploadRootDir().$this->getImageName());
}
$this->setImage($tempImageName);
}
/**
* #ORM\PostPersist()
*/
public function moveImage()
{
if (null === $this->image) {
return;
}
if(!is_dir($this->getUploadRootDir())){
mkdir($this->getUploadRootDir());
}
copy($this->getTmpUploadRootDir().$this->getImageName(), $this->getFullImagePath());
unlink($this->getTmpUploadRootDir().$this->getImageName());
}
/**
* #ORM\PreRemove()
*/
public function removeImage()
{
unlink($this->getFullImagePath());
rmdir($this->getUploadRootDir());
}
/**
* Set image
*
* #param string $image
* #return Book
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
/**
* Set image
*
* #param string $image
* #return Book
*/
public function setImageName($image)
{
$this->imageName = $image;
return $this;
}
/**
* Get image
*
* #return string
*/
public function getImageName()
{
return $this->imageName;
}
/**
* Constructor
*/
public function __construct()
{
$this->author = new ArrayCollection();
$this->reviews = new ArrayCollection();
$this->pictures = new ArrayCollection();
}
/**
* Add pictures
*
* #param \Library\MainBundle\Entity\Image $pictures
* #return Book
*/
public function addPicture(Image $pictures)
{
$this->pictures[] = $pictures;
$pictures->setBook($this);
return $this;
}
/**
* Remove pictures
*
* #param \Library\MainBundle\Entity\Image $pictures
*/
public function removePicture(Image $pictures)
{
$this->pictures->removeElement($pictures);
}
/**
* Get pictures
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getPictures()
{
return $this->pictures;
}
}
Image Entity (Image.php)
/**
* Image
*
* #ORM\Table(name="book_images")
* #ORM\HasLifecycleCallbacks
* #ORM\Entity(repositoryClass="Library\MainBundle\Entity\ImageRepository")
*/
class Image
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
* #Assert\File( maxSize = "1024k", mimeTypesMessage = "Please upload a valid Image")
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #ORM\ManyToOne(targetEntity="Book", inversedBy="pictures")
* #ORM\JoinColumn(name="book_id", referencedColumnName="id")
**/
private $book;
/**
* #var string
*/
private $imageName;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Image
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set book
*
* #param \Library\MainBundle\Entity\Book $book
* #return Image
*/
public function setBook(Book $book)
{
$this->book = $book;
return $this;
}
/**
* Get book
*
* #return \Library\MainBundle\Entity\Book
*/
public function getBook()
{
return $this->book;
}
/**
* Set image
*
* #param string $image
* #return Book
*/
public function setImageName($image)
{
$this->imageName = $image;
return $this;
}
/**
* Get image
*
* #return string
*/
public function getImageName()
{
return $this->imageName;
}
public function getFullImagePath() {
return null === $this->name ? null : $this->getUploadRootDir(). $this->name;
}
protected function getUploadRootDir() {
// the absolute directory path where uploaded documents should be saved
return $this->getTmpUploadRootDir().$this->getBook()->getId()."/";
}
protected function getTmpUploadRootDir() {
// the absolute directory path where uploaded documents should be saved
return __DIR__ . '/../../../../web/upload/books/';
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function uploadImage() {
// the file property can be empty if the field is not required
if (null === $this->name) {
return;
}
$tempImageName = time() . '_' .$this->name->getClientOriginalName();
if(!$this->getBook()->getId()){
$this->setImageName($this->name->getClientOriginalName());
$this->name->move($this->getTmpUploadRootDir(), $this->name->getClientOriginalName());
}else{
$this->name->move($this->getUploadRootDir(), $tempImageName);
unlink($this->getUploadRootDir().$this->getImageName());
}
$this->setName($tempImageName);
}
/**
* #ORM\PostPersist()
*/
public function moveImage()
{
if (null === $this->name) {
return;
}
if(!is_dir($this->getUploadRootDir())){
mkdir($this->getUploadRootDir());
}
copy($this->getTmpUploadRootDir().$this->getImageName(), $this->getFullImagePath());
unlink($this->getTmpUploadRootDir().$this->getImageName());
}
/**
* #ORM\PreRemove()
*/
public function removeImage()
{
unlink($this->getFullImagePath());
rmdir($this->getUploadRootDir());
}
}
My Forms :
BookType.php
namespace Library\MainBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Library\MainBundle\Entity\Role;
use Library\MainBundle\Entity\Image;
class BookType extends AbstractType
{
/**
* #var \Library\MainBundle\Entity\Role
*/
protected $publisherrole;
/**
* #var \Library\MainBundle\Entity\Role
*/
protected $authorrole;
public function __construct (Role $publisherRole, Role $authorRole)
{
$this->publisherrole = $publisherRole;
$this->authorrole = $authorRole;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text', array('label' => 'book.label.name',
'attr' => array('class' => 'element text medium')))
->add('subject', 'text', array('label' => 'book.label.subject',
'attr' => array('class' => 'element text medium')))
->add('isbn', 'text', array('label'=> 'book.label.isbn',
'attr' => array('class' => 'element text medium')))
->add('description', 'textarea', array('label' => 'book.label.description',
'attr' => array('class' => 'element textarea medium')))
->add('category', 'entity', array(
'class' => 'LibraryMainBundle:Category',
'property' => 'name',
"label" => 'book.label.category',
"attr" => array('class' => 'element select medium')))
->add('publisher', 'entity', array(
'class' => 'LibraryMainBundle:User',
'property' => 'name',
'label' => 'book.label.publisher',
'choices' => $this->publisherrole->getUser(),
'attr' => array('class' => 'element select medium')
))
->add('author', 'entity', array(
'class' => 'LibraryMainBundle:User',
'property' => 'name',
'label' => 'book.label.author',
'choices' => $this->authorrole->getUser(),
'multiple' => 'true',
'attr' => array('class' => 'element select medium')
))
->add('image', 'file', array('label' => 'book.label.coverpic',
'attr' => array('class' => 'element textarea medium'),
'data_class' => null
))
->add("pictures", 'collection', array(
'type'=>new FileType(),
'allow_add'=>true,
'by_reference' => true,
'data'=>array(new Image(),
new Image()
)
))
->add("save", "submit", array('label' => 'book.button.save'));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Library\MainBundle\Entity\Book'
));
}
/**
* #return string
*/
public function getName()
{
return 'library_mainbundle_book';
}
}
FileType.php
namespace Library\MainBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class FileType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
return $builder->add("name", "file");
}
public function getName()
{
return "filetype";
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class'=>'Library\MainBundle\Entity\Image',
'csrf_protection'=>true,
'csrf_field_name'=>'_token',
'intention'=>'file'
));
}
}
Please let me know if anything more required from my end.

Categories