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);
}
Related
I having some troubles with symfony forms.
I have a boolean variable in my entity. I cant find a way to set that value in my form when i'm editing it.
Entity
namespace AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="pages")
*/
class Page
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="text")
*/
protected $slug;
/**
* #ORM\Column(type="text")
*/
protected $title;
/**
* #ORM\Column(type="text")
*/
protected $content;
/**
* #ORM\Column(name="creation_date", type="datetime")
*/
protected $creationDate;
/**
* #ORM\Column(name="is_active", type="boolean")
*/
protected $isActive = true;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set slug
*
* #param string $slug
*
* #return Page
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* Set title
*
* #param string $title
*
* #return Page
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set content
*
* #param string $content
*
* #return Page
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content
*
* #return string
*/
public function getContent()
{
return $this->content;
}
/**
* Set creationDate
*
* #param \DateTime $creationDate
*
* #return Page
*/
public function setCreationDate($creationDate)
{
$this->creationDate = $creationDate;
return $this;
}
/**
* Get creationDate
*
* #return \DateTime
*/
public function getCreationDate()
{
return $this->creationDate;
}
/**
* Set isActive
*
* #param boolean $isActive
*
* #return Page
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
/**
* Get isActive
*
* #return boolean
*/
public function getIsActive()
{
return $this->isActive;
}
}
Controller function
public function editAction(Request $request, $pageId)
{
$em = $this->getDoctrine()->getManager();
$page = $em->getRepository('AdminBundle:Page')->find($pageId);
$form = $this->createForm('app_page', $page);
$form->handleRequest($request);
if($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($page);
$em->flush();
return $this->redirectToRoute('admin_pages');
}
return $this->render('AdminBundle::editPage.html.twig', array('page' => $page, 'form' => $form->createView()));
}
PageFormType
namespace AdminBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class PageFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('title', 'text');
$builder->add('slug', 'text');
$builder->add('isActive', 'choice', array('choices' => array(
'true' => 'Active',
'false' => 'Inactive'
)));
$builder->add('content', 'textarea', array('required' => false));
}
public function getName()
{
return 'app_page';
}
}
As you can see i wrote my self in FormType class what choices it has. And now it is always displaying "Active" instead of displaying Entity's value. How should i do that?
Thanks!
Try to change your isActive in the Entity like
protected $isActive ;
and if you want to make a default true you can make it at the construct like :
public function __construct() {
$this->setIsActive = true ;
}
$builder->add('isActive', ChoiceType::class, [
'choices' => [
'Active' => true,
'Inactive' => false
],
'choices_as_values' => true,
'multiple' => true,
'expanded' => true,
'data' => array(true)
]);
A 2021 Solution: setting form choice default value (data) from entity
Sometimes your choice field values exist in another entity table, which means you cannot populate them using default form data_class. You only get the string value that saved in the form entity, resulting to error: ...must be an object or null, string given...
protected EntityManagerInterface $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
// In your form
->add('membershipType', EntityType::class, [
'class' => MembershipType::class,
'label' => 'Enter membership type here',
'data' => $this->em->getRepository(MembershipType::class)->findOneBy([
'name' => $your_value_here
])
])
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(
...
))
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.. :)
I'm attempting to create a OneToOne Undirectional relationship between two entities. I've created the schema but when I submit the form it does not persist the data to the collection. Based off all my research I suspect it's because I don't have the owning entity set up correctly but I've tried everything I can to figure it out with no luck.
Entity - Products.php (Owning Side)
<?php
namespace SCWDesignsBundle\Entity\Products;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Mapping\ClassMetaData;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="SCWDesignsBundle\Entity\Repository\Products\ProductRespository")
* #ORM\Table(name="products")
*/
class Products {
/**
* #ORM\ID
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="ProductCategories")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
* #Assert\NotBlank()
*/
protected $category_id;
/**
* #ORM\Column(type="boolean", options={"default" = 0})
*/
protected $featured;
/**
* #ORM\Column(type="boolean", options={"default" = 1})
*/
protected $enabled;
/**
* #ORM\Column(type="boolean", options={"default" = 0})
*/
protected $free_shipping;
/**
* #ORM\OneToOne(targetEntity="ProductSales")
* #ORM\JoinColumn(name="participate_sale", referencedColumnName="id")
*/
protected $participate_sale;
/**
* #ORM\Column(type="decimal")
*/
protected $price;
/**
* #ORM\Column(type="integer")
*/
protected $sku;
/**
* #ORM\Column(type="datetime")
*/
protected $arrival_date;
/**
* #ORM\Column(type="datetime")
*/
protected $update_date;
/*
* ArrayCollection for ProductDescription
* #ORM\OneToOne(targetEntity="ProductDescription", mappedBy="product_id", cascade={"persist"})
* #ORM\JoinColumn(name="description", referencedColumnName="product_id")
*/
protected $description;
public function __construct() {
$this->setArrivalDate(new \DateTime());
$this->description = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set featured
*
* #param boolean $featured
* #return Products
*/
public function setFeatured($featured) {
$this->featured = $featured;
return $this;
}
/**
* Get featured
*
* #return boolean
*/
public function getFeatured() {
return $this->featured;
}
/**
* Set enabled
*
* #param boolean $enabled
* #return Products
*/
public function setEnabled($enabled) {
$this->enabled = $enabled;
return $this;
}
/**
* Get enabled
*
* #return boolean
*/
public function getEnabled() {
return $this->enabled;
}
/**
* Set free_shipping
*
* #param boolean $freeShipping
* #return Products
*/
public function setFreeShipping($freeShipping) {
$this->free_shipping = $freeShipping;
return $this;
}
/**
* Get free_shipping
*
* #return boolean
*/
public function getFreeShipping() {
return $this->free_shipping;
}
/**
* Set price
*
* #param string $price
* #return Products
*/
public function setPrice($price) {
$this->price = $price;
return $this;
}
/**
* Get price
*
* #return string
*/
public function getPrice() {
return $this->price;
}
/**
* Set sku
*
* #param integer $sku
* #return Products
*/
public function setSku($sku) {
$this->sku = $sku;
return $this;
}
/**
* Get sku
*
* #return integer
*/
public function getSku() {
return $this->sku;
}
/**
* Set arrival_date
*
* #param \DateTime $arrivalDate
* #return Products
*/
public function setArrivalDate($arrivalDate) {
$this->arrival_date = $arrivalDate;
return $this;
}
/**
* Get arrival_date
*
* #return \DateTime
*/
public function getArrivalDate() {
return $this->arrival_date;
}
/**
* Set update_date
*
* #param \DateTime $updateDate
* #return Products
*/
public function setUpdateDate($updateDate) {
$this->update_date = $updateDate;
return $this;
}
/**
* Get update_date
*
* #return \DateTime
*/
public function getUpdateDate() {
return $this->update_date;
}
/**
* Set category_id
*
* #param \SCWDesignsBundle\Entity\Products\ProductCategories $categoryId
* #return Products
*/
public function setCategoryId(\SCWDesignsBundle\Entity\Products\ProductCategories $categoryId = null) {
$this->category_id = $categoryId;
return $this;
}
/**
* Get category_id
*
* #return \SCWDesignsBundle\Entity\Products\ProductCategories
*/
public function getCategoryId() {
return $this->category_id;
}
/**
* Set participate_sale
*
* #param \SCWDesignsBundle\Entity\Products\ProductSales $participateSale
* #return Products
*/
public function setParticipateSale(\SCWDesignsBundle\Entity\Products\ProductSales $participateSale = null) {
$this->participate_sale = $participateSale;
return $this;
}
/**
* Get participate_sale
*
* #return \SCWDesignsBundle\Entity\Products\ProductSales
*/
public function getParticipateSale() {
return $this->participate_sale;
}
/**
* Set description
*
* #param \SCWDesignsBundle\Entity\Products\ProductDescrition $description
* #return Products
*/
public function setDescription($description) {
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription() {
return $this->description;
}
}
Entity - ProductDescription.php
<?php
namespace SCWDesignsBundle\Entity\Products;
use Doctrine\ORM\Mapping as ORM;
use SCWDesignsBundle\Entity\BaseEntity;
use Symfony\Component\Validator\Mapping\ClassMetaData;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="product_description")
*/
class ProductDescription extends BaseEntity {
/**
* #ORM\ManyToOne(targetEntity="Products")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $product_id;
/**
* #ORM\Column(type="string", columnDefinition="VARCHAR(255)")
* #Assert\Length(
* min = 2,
* max = 255,
* minMessage = "The item name must be at least {{ limit }} characters long.",
* maxMessage = "The item name cannot be longer than {{ limit }} characters."
* )
* #Assert\NotBlank()
*/
protected $name;
/**
* #ORM\Column(type="text")
* #Assert\NotBlank()
*/
protected $brief_description;
/**
* #ORM\Column(type="text")
* #Assert\NotBlank()
*/
protected $full_description;
/**
* #ORM\Column(type="string", columnDefinition="VARCHAR(255)")
* #Assert\Length(
* min = 2,
* max = 255,
* minMessage = "The tags characters must be at least {{ limit }} characters long.",
* maxMessage = "The tags characters cannot be longer than {{ limit }} characters."
* )
* #Assert\NotBlank()
*/
protected $meta_tags;
/**
* #ORM\Column(type="string", columnDefinition="VARCHAR(255)")
* #Assert\Length(
* min = 2,
* max = 255,
* minMessage = "The tags title must be at least {{ limit }} characters long.",
* maxMessage = "The tags title cannot be longer than {{ limit }} characters."
* )
* #Assert\NotBlank()
*/
protected $meta_title;
/**
* #ORM\Column(type="text")
* #Assert\NotBlank()
*/
protected $meta_description;
/**
* Set name
*
* #param string $name
* #return ProductDescription
*/
public function setName($name) {
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName() {
return $this->name;
}
/**
* Set brief_description
*
* #param string $briefDescription
* #return ProductDescription
*/
public function setBriefDescription($briefDescription) {
$this->brief_description = $briefDescription;
return $this;
}
/**
* Get brief_description
*
* #return string
*/
public function getBriefDescription() {
return $this->brief_description;
}
/**
* Set full_description
*
* #param string $fullDescription
* #return ProductDescription
*/
public function setFullDescription($fullDescription) {
$this->full_description = $fullDescription;
return $this;
}
/**
* Get full_description
*
* #return string
*/
public function getFullDescription() {
return $this->full_description;
}
/**
* Set meta_tags
*
* #param string $metaTags
* #return ProductDescription
*/
public function setMetaTags($metaTags) {
$this->meta_tags = $metaTags;
return $this;
}
/**
* Get meta_tags
*
* #return string
*/
public function getMetaTags() {
return $this->meta_tags;
}
/**
* Set meta_title
*
* #param string $metaTitle
* #return ProductDescription
*/
public function setMetaTitle($metaTitle) {
$this->meta_title = $metaTitle;
return $this;
}
/**
* Get meta_title
*
* #return string
*/
public function getMetaTitle() {
return $this->meta_title;
}
/**
* Set meta_description
*
* #param string $metaDescription
* #return ProductDescription
*/
public function setMetaDescription($metaDescription) {
$this->meta_description = $metaDescription;
return $this;
}
/**
* Get meta_description
*
* #return string
*/
public function getMetaDescription() {
return $this->meta_description;
}
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set product_id
*
* #param \SCWDesignsBundle\Entity\Products\Products $productId
* #return ProductDescription
*/
public function setProductId(\SCWDesignsBundle\Entity\Products\Products $productId = null) {
$this->product_id = $productId;
return $this;
}
/**
* Get product_id
*
* #return \SCWDesignsBundle\Entity\Products\Products
*/
public function getProductId() {
return $this->product_id;
}
}
FormType - NewProductFormType.php
<?php
namespace SCWDesignsBundle\Form\Admin;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use SCWDesignsBundle\Form\Types\ProductDescriptionType;
class NewProductFormType extends AbstractType {
private $entityManager;
public function __construct($entityManager) {
$this->entityManager = $entityManager;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('featured', 'checkbox', array('label' => 'Featured', 'required' => false))
->add('enabled', 'checkbox', array('label' => 'Enabled', 'required' => false))
->add('freeshipping', 'checkbox', array('label' => 'Free Shipping', 'required' => false))
// ->add('participate_sale', 'checkbox', array('label' => 'Sale', 'required' => false))
->add('price', 'text', array('label' => 'Price', 'required' => true))
->add('sku', 'text', array('label' => 'Sku', 'required' => false))
->add('description', 'collection', array(
'type' => new ProductDescriptionType(),
'allow_add' => true,
'by_reference' => true
))
->add('category_id', 'entity', array(
'class' => 'SCWDesignsBundle:Products\ProductCategories',
'property' => 'name',
'placeholder' => false
));
}
public function getName() {
return 'product_new';
}
}
Type - ProductDescriptionType.php
<?php
namespace SCWDesignsBundle\Form\Types;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ProductDescriptionType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name', null, array('label' => 'Product Name', 'required' => true))
->add('full_description', 'textarea', array('label' => 'Full Description', 'required' => false))
->add('brief_description', 'textarea', array('label' => 'Brief Description', 'required' => false))
->add('meta_tags', null, array('label' => 'Meta Tags', 'required' => false))
->add('meta_title', null, array('label' => 'Meta Title', 'required' => false))
->add('meta_description', 'text', array('label' => 'Meta Description', 'required' => false));
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array('data_class' => '\SCWDesignsBundle\Entity\Products\ProductDescription'));
}
public function getName() {
return 'product_description';
}
}
Controller - ProductsController.php
public function addProductAction(Request $request) {
$categories = $this->getCategories();
$em = $this->getDoctrine()->getEntityManager();
$product = new Products();
$form = $this->createForm(new NewProductFormType($em), $product);
$form->handleRequest($request);
if ($form->isValid()) {
$date = new \DateTime('NOW');
$product->setUpdateDate($date);
$em->persist($product);
$em->flush();
return $this->redirect($this->generateUrl('scw_designs_admin_products'));
}
return $this->render('SCWDesignsBundle:Admin\Products\Actions:new.html.twig', array(
'active_page' => 'products',
'categories' => $categories,
'form' => $form->createView(),
'action' => $this->generateUrl('scw_designs_admin_products_new')
));
}
As this caused me quite a bit of grief I've decided to post my answers after working with sshaun and ddproxy in the official #symfony irc channel.
First, I did have the owning relationship wrong. Needed to switch the inversedby to the product.php. Second I needed to presist the data, so I added the below to the controller and voila, as if magic, it worked.
if ($form->isValid()) {
$date = new \DateTime('NOW');
$product->setUpdateDate($date);
$em->persist($product);
$em->flush();
$description = $product->getDescription()->first();
$description->setProductId($product);
$em->persist($description);
$em->flush();
return $this->redirect($this->generateUrl('scw_designs_admin_products'));
}
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.