via EditController I let the user change his item. then I want to handle the update procedure in another Controller (UpdateController). But it does not work! He creates a new Item instead of updating the Item. In UpdateController I used dd (...) I found out that Id and Profile are not being forwarded to UpdateController.
Hopefully you can help me with it.
This is ItemEntity relationship met Profile
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Profile", inversedBy="items")
* #ORM\JoinColumn(nullable=false)
*/
private $profile;
This is ProfileEntity relationship met Items
/**
* #ORM\OneToMany(targetEntity="App\Entity\Items", mappedBy="profile")
*/
private $items;
This is EditController
/**
* #IsGranted("ROLE_USER")
* Class EditController
* #package App\Controller
*/
final class EditController extends AbstractController
{
/**
* #Route("/item/edit/{items}", name="edit_item")
*
* #param Items $items
* #return Response
*/
public function edit(Items $items)
{
$form = $this->createForm(CreateTodoFormType::class, $items, ['action' => $this->generateUrl('update_item')]);
return $this->render('item/edit.html.twig', [
'todoForm' => $form->createView(),
'viewData' => $form->getViewData()
]);
}
}
This is UpdateController
/**
* #IsGranted("ROLE_USER")
* Class UpdateController
* #package App\Controller\Item
*/
final class UpdateController extends AbstractController
{
/**
* #Route("/item/update", name="update_item", methods={"POST"})
*/
public function update(EntityManagerInterface $em, Request $request, TranslatorInterface $translator)
{
$form = $this->createForm(CreateTodoFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$item = $form->getData();
$profile = $em->getRepository(Profile::class)->findProfileById($this->getUser()->getId());
$item->setProfile($profile);
$em->persist($item);
$em->flush();
$this->addFlash('success', $translator->trans('The new ToDo is updated.'));
return $this->redirectToRoute('item');
}
return $this->render('item/edit.html.twig', [
'todoForm' => $form->createView(),
]);
}
}
Related
Hi and thank you for taking the time reading this.
English is not my first language so I hope you'll excuse me for any errors.
Currently I'm doing a project to get familiar with Symfony 3.
This is what I'm trying to do:
I have a oneToMany relation, Game to PlayLog.
The relation is established and I can view a list of dates in my games.
I want to create a new PlayLog and be associated with the Game so I can access all my related PlayLogs via Game.
A view is shown with the id of the game (log.html.twig)
My question:
How do I create a new PlayLog with a form and date formField(dateType), and add it to an existing game?
Update: with the current code I now get this error:
An exception occurred while executing 'INSERT INTO play_log (date,
game_id) VALUES (?, ?)' with params ["2017-03-04", null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'game_id'
cannot be null
This is my code:
--- entity/Game.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Game
*
* #ORM\Table(name="game")
* #ORM\Entity(repositoryClass="AppBundle\Repository\GameRepository")
*/
class Game
{
/**
* #ORM\OneToMany(targetEntity="PlayLog", mappedBy="game")
*/
private $playlogs;
public function __construct()
{
$this->playlogs = new ArrayCollection();
}
/**
* #ORM\ManyToOne(targetEntity="Type", inversedBy="games")
* #ORM\JoinColumn(name="type_id", referencedColumnName="id")
*/
private $type;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
* #Assert\NotBlank()
* #Assert\Length(
* min = "3",
* max = "100"
* )
* #ORM\Column(name="name", type="string", length=255, unique=true)
*/
private $name;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Game
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #return mixed
*/
public function getType()
{
return $this->type;
}
/**
* #ORM\Column (options={"default" = none})
* #param mixed $type
*/
public function setType($type)
{
$this->type = $type;
}
/**
* #return mixed
*/
public function getPlaylogs()
{
return $this->playlogs;
}
/**
* #param mixed $playlogs
*/
public function setPlaylogs($playlogs)
{
$this->playlogs = $playlogs;
}
public function addPlayLog(PlayLog $playlog)
{
$this->playlog->add($playlog);
$playlog->setPlayLogs($this);
}
}
--- entity/PlayLog.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* PlayLog
*
* #ORM\Table(name="play_log")
* #ORM\Entity(repositoryClass="AppBundle\Repository\PlayLogRepository")
*/
class PlayLog
{
/**
* #ORM\ManyToOne(targetEntity="Game", inversedBy="playlogs")
* #ORM\JoinColumn(name="game_id", referencedColumnName="id")
*/
private $game;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="date")
*/
private $date;
/**
* #var int
*
* #ORM\Column(name="game_id", type="integer")
*/
private $gameId;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set date
*
* #param \DateTime $date
*
* #return PlayLog
*/
public function setDate($date)
{
$this->date = $date;
return $this;
}
/**
* Get date
*
* #return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* Set gameId
*
* #param integer $gameId
*
* #return PlayLog
*/
public function setGameId($gameId)
{
$this->gameId = $gameId;
return $this;
}
/**
* Get gameId
*
* #return int
*/
public function getGameId()
{
return $this->gameId;
}
public function addGame(Game $game)
{
$this->games->add($game);
$game->setType($this);
}
public function removeGame(Game $game)
{
$this->games->removeElement($game);
}
}
--- GameController.php
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\Game;
use AppBundle\Entity\PlayLog;
use AppBundle\Entity\Type;
use AppBundle\Form\GameType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\HttpFoundation\Request;
/**
* Game controller.
*
* #Route("game")
*/
class GameController extends Controller
{
/**
* Lists all game entities.
*
* #Route("/", name="game_index")
* #Method("GET")
*/
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
// $games = $em->getRepository('AppBundle:Game')->findAll();
$dql = "SELECT game FROM AppBundle:Game game JOIN game.type type ORDER BY game.name";
$query = $em->createQuery($dql);
/*
* #var $paginator \Knp\Component\Pager\Paginator
*/
$paginator = $this->get('knp_paginator');
$result = $paginator->paginate(
$query,
$request->query->getInt('page', 1),
$request->query->getInt('limit', 25)
);
// dump(get_class($paginator));
return $this->render('game/index.html.twig', array(
'games' => $result,
'max_limit_error' => 25
));
}
/**
* Creates a new game entity.
*
* #Route("/new", name="game_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$game = new Game();
$form = $this->createForm('AppBundle\Form\GameType', $game);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($game);
$em->flush($game);
return $this->redirectToRoute('game_show', array('id' => $game->getId()));
}
return $this->render('game/new.html.twig', array(
'game' => $game,
'form' => $form->createView(),
));
}
/**
* Finds and displays a game entity.
*
* #Route("/{id}", name="game_show")
* #Method("GET")
*/
public function showAction(Game $game)
{
$deleteForm = $this->createDeleteForm($game);
return $this->render('game/show.html.twig', array(
'game' => $game,
'delete_form' => $deleteForm->createView(),
));
}
/**
* Displays a form to edit an existing game entity.
*
* #Route("/{id}/edit", name="game_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, Game $game)
{
$deleteForm = $this->createDeleteForm($game);
$editForm = $this->createForm('AppBundle\Form\GameType', $game);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('game_show', array('id' => $game->getId()));
}
return $this->render('game/edit.html.twig', array(
'game' => $game,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
/**
* Displays a form to edit an existing game entity.
*
* #Route("/{id}/log", name="game_log")
* #Method({"GET", "POST"})
*/
public function addLogAction(Request $request, Game $game)
{
$playlog = new PlayLog();
$form = $this->createForm(GameType::class, $game);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
//Save playLog
$em = $this->getDoctrine()->getManager();
$em->persist($playlog);
$em->flush();
}
// Render / return view incl. formulier.
return $this->render('game/log.html.twig', array(
'game' => $game,
'form' => $form->createView(),
));
}
/**
* Deletes a game entity.
*
* #Route("/{id}", name="game_delete")
* #Method("DELETE")
*/
public function deleteAction(Request $request, Game $game)
{
$form = $this->createDeleteForm($game);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->remove($game);
$em->flush($game);
}
return $this->redirectToRoute('game_index');
}
/**
* Creates a form to delete a game entity.
*
* #param Game $game The game entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm(Game $game)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('game_delete', array('id' => $game->getId())))
->setMethod('DELETE')
->getForm()
;
}
}
--- PlayLogController.php
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\PlayLog;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Symfony\Component\HttpFoundation\Request;
/**
* Playlog controller.
*
* #Route("playlog")
*/
class PlayLogController extends Controller
{
/**
* Lists all playLog entities.
*
* #Route("/", name="playlog_index")
* #Method("GET")
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$playLogs = $em->getRepository('AppBundle:PlayLog')->findAll();
return $this->render('playlog/index.html.twig', array(
'playLogs' => $playLogs,
));
}
/**
* Creates a new playLog entity.
*
* #Route("/{gameId}/new", name="playlog_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request, $gameId)
{
$playlog = new PlayLog();
$form = $this->createForm('AppBundle\Form\PlayLogType', $playlog);
$form->handleRequest($request);
$playlog->setGameId($gameId);
echo $playlog->getGameId()."!";
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($playlog);
$em->flush();
// return $this->redirectToRoute('game_show', array('id' => $gameId));
}
return $this->render('playlog/new.html.twig', array(
'playLog' => $playlog,
'form' => $form->createView(),
));
}
return $this->render('playlog/new.html.twig', array(
'playLog' => $playLog,
'form' => $form->createView(),
));
}
/**
* Finds and displays a playLog entity.
*
* #Route("/{id}", name="playlog_show")
* #Method("GET")
*/
public function showAction(PlayLog $playLog)
{
$deleteForm = $this->createDeleteForm($playLog);
return $this->render('playlog/show.html.twig', array(
'playLog' => $playLog,
'delete_form' => $deleteForm->createView(),
));
}
/**
* Displays a form to edit an existing playLog entity.
*
* #Route("/{id}/edit", name="playlog_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, PlayLog $playLog)
{
$deleteForm = $this->createDeleteForm($playLog);
$editForm = $this->createForm('AppBundle\Form\PlayLogType', $playLog);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('playlog_edit', array('id' => $playLog->getId()));
}
return $this->render('playlog/edit.html.twig', array(
'playLog' => $playLog,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
/**
* Deletes a playLog entity.
*
* #Route("/{id}", name="playlog_delete")
* #Method("DELETE")
*/
public function deleteAction(Request $request, PlayLog $playLog)
{
$form = $this->createDeleteForm($playLog);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->remove($playLog);
$em->flush();
}
return $this->redirectToRoute('playlog_index');
}
/**
* Creates a form to delete a playLog entity.
*
* #param PlayLog $playLog The playLog entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm(PlayLog $playLog)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('playlog_delete', array('id' => $playLog->getId())))
->setMethod('DELETE')
->getForm()
;
}
}
--- game/log.html.twig
{% extends 'base.html.twig' %}
{% block content %}
Adding log for {{ game.name }}
{{ form_widget(form.playlogs) }}
<input type="submit" value="Create" class="btn btn-default pull-left" />
{% endblock content %}
--- PlayLogType.php
<?php
namespace AppBundle\Form;
use AppBundle\Entity\PlayLog;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PlayLogType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('date');
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => PlayLog::class
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_playlog';
}
}
--- GameType.php
<?php
namespace AppBundle\Form;
use AppBundle\Entity\PlayLog;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class GameType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class, [
'attr' => [
'class' => 'form-control',
],
]);
$builder
->add('type', EntityType::class, [
'class' => 'AppBundle:Type',
'choice_label' => function ($type) {
return $type->getName();
},
'multiple' => false,
'expanded' => false,
'attr' => [
'class' => 'form-control',
],
]);
$builder->add('playlogs', CollectionType::class, array(
'entry_type' => PlayLogType::class,
'label' => false
));
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Game'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_game';
}
}
Not sure if this is the answer you looking for..
You can tweek your newAction and his Route annotation in the Playlog controller a bit so that you add the gameId in the route
/**
* Creates a new playLog entity.
*
* #Route("/{gameId}/new", name="playlog_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request, $gameId)
{
$em = $this->getDoctrine()->getManager();
$game = $em->getRepository('AppBundle:Game')->find($gameId);
if(null === $game) {
throw $this->createNotFoundException('The game with id ' . $gameId . ' does not exist.');
}
$playLog = new Playlog();
$playLog->SetGame($game);
$form = $this->createForm('AppBundle\Form\PlayLogType', $playLog);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($playLog);
$em->flush($playLog);
return $this->redirectToRoute('playlog_show', array('id' => $playLog->getId()));
}
return $this->render('playlog/new.html.twig', array(
'playLog' => $playLog,
'form' => $form->createView(),
));
}
I've figured it out, I tried to persist with just an ID ($gameId) but it expected the entire Game object. (1) So I first had to get the actual repository object with the ID and after that I can persist this object:
public function newAction(Request $request, $gameId)
{
$playlog = new PlayLog();
$em = $this->getDoctrine()->getManager();
// (1) Get Game object with given gameId:
$game = $em ->getRepository(Game::class)->find($gameId);
//Set the Game object
$playlog->setGame($game);
$form = $this->createForm('AppBundle\Form\PlayLogType', $playlog);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/* #var $playLog PlayLog */
$playlog = $form->getData();
$em->persist($playlog);
$em->flush();
}
return $this->render('playlog/new.html.twig', array(
'playLog' => $playlog,
'form' => $form->createView(),
));
}
How to implement NotifyPropertyChanged for retrieving entity changes (in Symfony 2.8 project with doctrine)?
I have found several examples, but they are not full:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html
http://www.boostr.in/26896/is-there-a-built-in-way-to-get-all-of-the-changed-updated-fields-in-a-doctrine-2%23googleads
For me it is not clear if i have to implement the own onPropertyChanged function, how ? I would like to retrive the property changes naming the last and the current properties in the controller and format them as a message for the user.
When i search in the documentation, NotifyPropertyChanged is not described or described minimally:
http://symfony2-document.readthedocs.io/en/latest/search.html?q=NotifyPropertyChanged&check_keywords=yes&area=default
http://api.symfony.com/2.8/search.html?search=NotifyPropertyChanged
http://docs.w3cub.com/symfony~2.8/
http://phpdox.de/demo/Symfony2/interfaces/Doctrine_Common_NotifyPropertyChanged.xhtml
It is written that addPropertyChangedListener() — Adds a listener that wants to be notified about property changes. I do not understand how i should put the custom code in this listener and how to execute this listener in such a way, that i could retrieve the entity changes to the controller action.
// src\MeetingBundle\Entity\EventLisObject.php
<?php
namespace MeetingBundle\Entity;
use Doctrine\Common\NotifyPropertyChanged;
use Doctrine\Common\PropertyChangedListener;
abstract class EventLisObject implements NotifyPropertyChanged
{
private $listeners = array();
public function addPropertyChangedListener(PropertyChangedListener $listener) {
$this->listeners[] = $listener;
}
/** Notifies listeners of a change. */
protected function onPropertyChanged($propName, $oldValue, $newValue) {
if ($this->listeners) {
foreach ($this->listeners as $listener) {
$listener->propertyChanged($this, $propName, $oldValue, $newValue);
}
}
}
}
//C src\MeetingBundle\Entity\Event.php
<?php
namespace MeetingBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Event
*
* #ORM\Table(name="tevent", indexes={#ORM\Index(columns={"keywords"}, flags={"fulltext"})})
* #ORM\Entity(repositoryClass="MeetingBundle\Repository\EventRepository" )
*/
class Event extends EventLisObject
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
* #Assert\NotBlank()
*/
private $title;
/**
* Set title
*
* #param string $title
*
* #return Event
*/
public function setTitle($title) {
// $this->title = $title;
if( $title != $this->title ) {
$this->_onPropertyChanged("title", $this->title, $title);
$this->title = $title; }
return $this;
}
// src\MeetingBundle\Controller\EventMapControllerACL.php
....
/**
* Event controller.
*
* #Route("/eventmapacl")
*/
class EventMapControllerACL extends Controller
{
/**
* #Route("/edit/{id}", name="event_jsMap_edit")
* #Method("GET|POST")
* #Template("MeetingBundle:Event:ev_jsMap_edit.html.twig")
*/
public function editAction($id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('MeetingBundle:Event')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Event entity.');
}
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
// $deleteForm = $this->createDeleteForm($id);
if ($editForm->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
// here or before flush or before persist i would like to estimate the changes and generate the message to user informing about them.
return $this->redirect($this->generateUrl('event_jsMap_edit', array('id' => $entity->getId())));
}
return array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
);
}
I followed the documentation for this here: but could not get the example to persist to the database for the embedded form; the Plant class saved just fine. I am under the assumption that the persist and flush methods in the controller handle the persisting of both entities. Is this wrong to assume? Do I need to intercept it and set it manually in the controller before flush?
At any rate, here is my code:
Plant Entity:
<?php
/**
* #ORM\Entity(repositoryClass="Blogger\BlogBundle\Entity\Repository\PlantRepository")
* #ORM\Table(name="plant")
* #ORM\HasLifecycleCallbacks
*/
class Plant
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="array", nullable=true)
* #ORM\ManyToMany(targetEntity="Blogger\BlogBundle\Entity\Picture", inversedBy="plants", cascade={"persist"})
* #ORM\JoinTable(name="picture")
*/
protected $pictures;
//...
public function __construct()
{
$this->pictures = new ArrayCollection;
}
//...
/**
* Add pictures
*
* #param \Blogger\BlogBundle\Entity\Picture $pictures
* #return Plant
*/
public function addPicture(\Blogger\BlogBundle\Entity\Picture $pictures)
{
$pictures->addPlant($this);
$this->pictures[] = $pictures;
}
/**
* Remove pictures
*
* #param \Blogger\BlogBundle\Entity\Picture $pictures
*/
public function removePicture(\Blogger\BlogBundle\Entity\Picture $pictures)
{
$this->pictures->removeElement($pictures);
}
/**
* Get pictures
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getPictures()
{
return $this->pictures;
}
}
Picture Entity:
<?php
namespace Blogger\BlogBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="Picture")
*/
class Picture
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
//...
/**
* #ORM\Column(type="text")
*/
public $path;
/**
* #ORM\Column(type="array", nullable=true)
* #ORM\ManyToMany(targetEntity="Blogger\BlogBundle\Entity\Plant", mappedBy="pictures")
*/
private $plants;
/**
* Constructor
*/
public function __construct()
{
$this->plants = new \Doctrine\Common\Collections\ArrayCollection();
}
//...
/**
* Set path
*
* #param string $path
* #return Picture
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* Get path
*
* #return string
*/
public function getPath()
{
return $this->path;
}
/**
* Add plants
*
* #param \Blogger\BlogBundle\Entity\Plant $plants
* #return Picture
*/
public function addPlant(\Blogger\BlogBundle\Entity\Plant $plants)
{
if (!$this->plants->contains($plants)) {
$this->plants->add($plants);
}
}
/**
* Remove plants
*
* #param \Blogger\BlogBundle\Entity\Plant $plants
*/
public function removePlant(\Blogger\BlogBundle\Entity\Plant $plants)
{
$this->plants->removeElement($plants);
}
/**
* Get plants
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getPlants()
{
return $this->plants;
}
}
Plant Form:
<?php
namespace Blogger\BlogBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PlantForm extends AbstractType
{
public function __construct($em) {
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
//...
$builder->add('pictures', 'collection', array(
'type' => new PictureForm(),
'options' => array(
'data_class' => 'Blogger\BlogBundle\Entity\Picture'),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Blogger\BlogBundle\Entity\Plant',
));
}
public function getName()
{
return 'plant';
}
}
Picture Form:
<?php
namespace Blogger\BlogBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PictureForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
//...
$builder->add('path', 'textarea');
//...
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Blogger\BlogBundle\Entity\Picture',
));
}
public function getName()
{
return 'picture';
}
}
Plant Controller:
public function newAction(Request $request){
$plant = new Plant();
$image1 = new Picture();
$plant->getPictures()->add($image1);
$form = $this->createForm(new PlantForm($this->getDoctrine()->getManager()), $plant);
if ($request->getMethod() == 'POST') {
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()
->getEntityManager();
$em->persist($plant);
$em->flush();
return $this->redirect($this->generateUrl('route', array(
'id' => $plant->getId()
)));
}
}
return $this->render('Bundle:Plant:new.html.twig', array(
'form' => $form->createView()
));
}
I suspect I don't have my annotations for the database mapped correctly. When I open phpadmin, there are no relationships defined in the database.
I figured it out. It was indeed an error with my annotations. This question was actually answered in a post here. For my solution, it looked like this:
Plant entity:
class Plant
{
//..
/**
* #ORM\ManyToMany(targetEntity="Blogger\BlogBundle\Entity\Picture", inversedBy="plants", cascade={"persist"})
* #ORM\JoinColumn(nullable=false, onDelete="CASCADE")
*/
protected $pictures;
/**
* Constructor
*/
public function __construct()
{
$this->pictures = new ArrayCollection();
}
public function addPicture(\Blogger\BlogBundle\Entity\Picture $pictures)
{
$pictures->addPlant($this);
$this->pictures[] = $pictures;
}
//..
}
class Picture
{
//..
/**
* #ORM\ManyToMany(targetEntity="Blogger\BlogBundle\Entity\Plant", mappedBy="pictures", cascade={"persist", "remove"})
*/
private $plants;
/**
* Constructor
*/
public function __construct()
{
$this->plants = new \Doctrine\Common\Collections\ArrayCollection();
}
public function addPlant(\Blogger\BlogBundle\Entity\Plant $plants)
{
if (!$this->plants->contains($plants)) {
$this->plants->add($plants);
}
}
//..
}
Controller:
public function newAction(Request $request){
$plant = new Plant();
if ($request->getMethod() == 'POST') {
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()
->getEntityManager();
$em->persist($plant);
$em->flush();
return $this->redirect($this->generateUrl('BloggerBlogBundle_plant_library_show', array(
'id' => $plant->getId()
)));
}
}
return $this->render('BloggerBlogBundle:Library:new.html.twig', array(
'form' => $form->createView()
));
}
Maybe a useful note to others: this mapping created a new table called plant_picture which holds the association. I was surprised to learn that a "picture" column was NOT added to the Plant entity at all.
i'm having trouble with crud and user entity ( playing a little with sf2). i've been following the symfony cookbook for saving users in database and roles and i've generated crud for user entity and role entity. on user entity i have the field for assigning the role yet in the select option it shows the id of the role instead of the name and i'm not sure how modify the field to show the role name. can you help me please ?
User Controller:
namespace UserBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use UserBundle\Entity\User;
use UserBundle\Form\UserType;
/**
* User controller.
*
* #Route("/user")
*/
class UserController extends Controller
{
/**
* Lists all User entities.
*
* #Route("/", name="user")
* #Method("GET")
* #Template()
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('UserBundle:User')->findAll();
return array(
'entities' => $entities,
);
}
/**
* Creates a new User entity.
*
* #Route("/", name="user_create")
* #Method("POST")
* #Template("UserBundle:User:new.html.twig")
*/
public function createAction(Request $request)
{
$entity = new User();
$factory = $this->get('security.encoder_factory');
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
$encoder = $factory->getEncoder($entity);
$password = $encoder->encodePassword($entity->getPassword(), $entity->getSalt());
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('user_show', array('id' => $entity->getId())));
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
/**
* Creates a form to create a User entity.
*
* #param User $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(User $entity)
{
$form = $this->createForm(new UserType(), $entity, array(
'action' => $this->generateUrl('user_create'),
'method' => 'POST',
));
$form->add('submit', 'submit', array('label' => 'Create'));
return $form;
}
/**
* Displays a form to create a new User entity.
*
* #Route("/new", name="user_new")
* #Method("GET")
* #Template()
*/
public function newAction()
{
$entity = new User();
$form = $this->createCreateForm($entity);
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
/**
* Finds and displays a User entity.
*
* #Route("/{id}", name="user_show")
* #Method("GET")
* #Template()
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('UserBundle:User')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find User entity.');
}
$deleteForm = $this->createDeleteForm($id);
return array(
'entity' => $entity,
'delete_form' => $deleteForm->createView(),
);
}
/**
* Displays a form to edit an existing User entity.
*
* #Route("/{id}/edit", name="user_edit")
* #Method("GET")
* #Template()
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('UserBundle:User')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find User entity.');
}
$editForm = $this->createEditForm($entity);
$deleteForm = $this->createDeleteForm($id);
return array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
);
}
/**
* Creates a form to edit a User entity.
*
* #param User $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createEditForm(User $entity)
{
$form = $this->createForm(new UserType(), $entity, array(
'action' => $this->generateUrl('user_update', array('id' => $entity->getId())),
'method' => 'PUT',
));
$form->add('submit', 'submit', array('label' => 'Update'));
return $form;
}
/**
* Edits an existing User entity.
*
* #Route("/{id}", name="user_update")
* #Method("PUT")
* #Template("UserBundle:User:edit.html.twig")
*/
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('UserBundle:User')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find User entity.');
}
$deleteForm = $this->createDeleteForm($id);
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('user_edit', array('id' => $id)));
}
return array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
);
}
/**
* Deletes a User entity.
*
* #Route("/{id}", name="user_delete")
* #Method("DELETE")
*/
public function deleteAction(Request $request, $id)
{
$form = $this->createDeleteForm($id);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('UserBundle:User')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find User entity.');
}
$em->remove($entity);
$em->flush();
}
return $this->redirect($this->generateUrl('user'));
}
/**
* Creates a form to delete a User entity by id.
*
* #param mixed $id The entity id
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm($id)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('user_delete', array('id' => $id)))
->setMethod('DELETE')
->add('submit', 'submit', array('label' => 'Delete'))
->getForm()
;
}
}
UserType
<?php
namespace UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UserType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('username')
->add('password')
->add('email')
->add('isActive')
->add('roles')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'UserBundle\Entity\User'
));
}
/**
* #return string
*/
public function getName()
{
return 'userbundle_user';
}
}
UserEntity
<?php
namespace UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* UserBundle\Entity\User
*
* #ORM\Table(name="acme_users")
* #ORM\Entity(repositoryClass="UserBundle\Entity\UserRepository")
*/
class User implements UserInterface, \Serializable
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=25, unique=true)
*/
private $username;
/**
* #ORM\Column(type="string", length=64)
*/
private $password;
/**
* #ORM\Column(type="string", length=60, unique=true)
*/
private $email;
/**
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
* #ORM\ManyToMany(targetEntity="Role", inversedBy="users")
*/
private $roles;
public function __construct()
{
$this->isActive = true;
$this->roles = new ArrayCollection();
// may not be needed, see section on salt below
// $this->salt = md5(uniqid(null, true));
}
/**
* #inheritDoc
*/
public function getUsername()
{
return $this->username;
}
/**
* #inheritDoc
*/
public function getSalt()
{
// you *may* need a real salt depending on your encoder
// see section on salt below
return null;
}
/**
* #inheritDoc
*/
public function getPassword()
{
return $this->password;
}
/**
* #inheritDoc
*/
public function getRoles()
{
return $this->roles->toArray();
}
/**
* #inheritDoc
*/
public function eraseCredentials()
{
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->password,
// see section on salt below
// $this->salt,
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
// see section on salt below
// $this->salt
) = unserialize($serialized);
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Set password
*
* #param string $password
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Set email
*
* #param string $email
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set isActive
*
* #param boolean $isActive
* #return User
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
/**
* Get isActive
*
* #return boolean
*/
public function getIsActive()
{
return $this->isActive;
}
/**
* Add roles
*
* #param \UserBundle\Entity\Role $roles
* #return User
*/
public function addRole(\UserBundle\Entity\Role $roles)
{
$this->roles[] = $roles;
return $this;
}
/**
* Remove roles
*
* #param \UserBundle\Entity\Role $roles
*/
public function removeRole(\UserBundle\Entity\Role $roles)
{
$this->roles->removeElement($roles);
}
public function __toString() {
return (string) $this->getId();
}
}
Implement __toString() method in the Role entity class.
public function __toString()
{
return $this->name;
}
You could also pass 'property' => 'name' option to roles field
Read more about other form type options here http://symfony.com/doc/current/reference/forms/types/entity.html
I have an Entity in Symfony called Ip and I save my IP address as integer - I use the IP as primary key, too.
But when I display and enter the IP in a form or list I want to convert it to a IP, e.g. 127.0.0.1 is saved as 2130706433.
I created the forms with the CRUD generator.
My entity comes here:
<?php
namespace IS\ClearanceBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* IS\ClearanceBundle\Entity\Ip
*/
class Ip
{
/**
* #var bigint $ip
*/
private $ip;
/**
* #var integer $high
*/
private $high;
/**
* #var string $hoster
*/
private $hoster;
/**
* #var datetime $scandate
*/
private $scandate;
/**
* #var integer $id
*/
private $id;
/**
* #var IS\ClearanceBundle\Entity\Clearance
*/
private $clearance;
public function __construct()
{
$this->clearance = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Set ip
*
* #param bigint $ip
*/
public function setIp($ip)
{
$this->ip = $ip;
}
/**
* Get ip
*
* #return bigint
*/
public function getIp()
{
return $this->ip;
}
/**
* Set high
*
* #param integer $high
*/
public function setHigh($high)
{
$this->high = $high;
}
/**
* Get high
*
* #return integer
*/
public function getHigh()
{
return $this->high;
}
/**
* Set hoster
*
* #param string $hoster
*/
public function setHoster($hoster)
{
$this->hoster = $hoster;
}
/**
* Get hoster
*
* #return string
*/
public function getHoster()
{
return $this->hoster;
}
/**
* Set scandate
*
* #param datetime $scandate
*/
public function setScandate($scandate)
{
$this->scandate = $scandate;
}
/**
* Get scandate
*
* #return datetime
*/
public function getScandate()
{
return $this->scandate;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Add clearance
*
* #param IS\ClearanceBundle\Entity\Clearance $clearance
*/
public function addClearance(\IS\ClearanceBundle\Entity\Clearance $clearance)
{
$this->clearance[] = $clearance;
}
/**
* Get clearance
*
* #return Doctrine\Common\Collections\Collection
*/
public function getClearance()
{
return $this->clearance;
}
}
And here is my Controller:
<?php
namespace IS\ClearanceBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use IS\ClearanceBundle\Entity\Ip;
use IS\ClearanceBundle\Form\IpType;
/**
* Ip controller.
*
* #Route("/ip")
*/
class IpController extends Controller
{
/**
* Lists all Ip entities.
*
* #Route("/", name="ip")
* #Template()
*/
public function indexAction()
{
$em = $this->getDoctrine()->getEntityManager();
$entities = $em->getRepository('ISClearanceBundle:Ip')->findAll();
return array('entities' => $entities);
}
/**
* Finds and displays a Ip entity.
*
* #Route("/{id}/show", name="ip_show")
* #Template()
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('ISClearanceBundle:Ip')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Ip entity.');
}
$deleteForm = $this->createDeleteForm($id);
return array(
'entity' => $entity,
'delete_form' => $deleteForm->createView(), );
}
/**
* Displays a form to create a new Ip entity.
*
* #Route("/new", name="ip_new")
* #Template()
*/
public function newAction()
{
$entity = new Ip();
$form = $this->createForm(new IpType(), $entity);
return array(
'entity' => $entity,
'form' => $form->createView()
);
}
/**
* Creates a new Ip entity.
*
* #Route("/create", name="ip_create")
* #Method("post")
* #Template("ISClearanceBundle:Ip:new.html.twig")
*/
public function createAction()
{
$entity = new Ip();
$request = $this->getRequest();
$form = $this->createForm(new IpType(), $entity);
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('ip_show', array('id' => $ entity->getId())));
}
return array(
'entity' => $entity,
'form' => $form->createView()
);
}
/**
* Displays a form to edit an existing Ip entity.
*
* #Route("/{id}/edit", name="ip_edit")
* #Template()
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('ISClearanceBundle:Ip')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Ip entity.');
}
$editForm = $this->createForm(new IpType(), $entity);
$deleteForm = $this->createDeleteForm($id);
return array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
);
}
/**
* Edits an existing Ip entity.
*
* #Route("/{id}/update", name="ip_update")
* #Method("post")
* #Template("ISClearanceBundle:Ip:edit.html.twig")
*/
public function updateAction($id)
{
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('ISClearanceBundle:Ip')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Ip entity.');
}
$editForm = $this->createForm(new IpType(), $entity);
$deleteForm = $this->createDeleteForm($id);
$request = $this->getRequest();
$editForm->bindRequest($request);
if ($editForm->isValid()) {
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('ip_edit', array('id' => $ id)));
}
return array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
);
}
/**
* Deletes a Ip entity.
*
* #Route("/{id}/delete", name="ip_delete")
* #Method("post")
*/
public function deleteAction($id)
{
$form = $this->createDeleteForm($id);
$request = $this->getRequest();
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('ISClearanceBundle:Ip')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Ip entity.' );
}
$em->remove($entity);
$em->flush();
}
return $this->redirect($this->generateUrl('ip'));
}
private function createDeleteForm($id)
{
return $this->createFormBuilder(array('id' => $id))
->add('id', 'hidden')
->getForm()
;
}
}
And here the form:
<?php
namespace IS\ClearanceBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class IpType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('ip')
->add('high')
->add('hoster')
->add('scandate')
->add('clearance','entity', array('class'=>'IS\ClearanceBundle\Entity\Clearance', 'property'=>'id','required'=>false, 'multiple'=>true))
;
}
public function getName()
{
return 'is_clearancebundle_iptype';
}
}
Thanks for any help!
IMO if you want do it, you should use data transformer http://symfony.com/doc/current/cookbook/form/data_transformers.html and implement __toString for your entity IP.
EDIT:
Created sample at gist: https://gist.github.com/3086241