Combine Questionnaire with User entity in form - symfony2 - php

I need to add questionnaire of multiple choice questions to my registration form. The questions and options are in two entities:
<?php
namespace Me\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Question
*
* #ORM\Table(name="question")
* #ORM\Entity(repositoryClass="Me\UserBundle\Entity\QuestionRepository")
*/
class Question
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="questionText", type="text")
*/
private $questionText;
/**
* #var boolean $expanded
*
* #ORM\Column(name="expanded", type="boolean")
*/
private $expanded;
/**
* #var boolean $multiple
*
* #ORM\Column(name="multiple", type="boolean")
*/
private $multiple;
/**
* #var Questionnaire $questionnaire
*
* #ORM\ManyToOne(targetEntity="Questionnaire", inversedBy="questions")
* #ORM\JoinColumn(name="questionnaire", referencedColumnName="id", onDelete="cascade")
*/
private $questionnaire;
/**
* #var \Doctrine\Common\Collections\ArrayCollection $options
*
* #ORM\OneToMany(targetEntity="Option", mappedBy="question", cascade={"all"})
*/
private $options;
public function __construct()
{
$this->expanded = false;
$this->multiple = false;
$this->options = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set questionText
*
* #param string $questionText
* #return Question
*/
public function setQuestionText($questionText)
{
$this->questionText = $questionText;
return $this;
}
/**
* Get questionText
*
* #return string
*/
public function getQuestionText()
{
return $this->questionText;
}
/**
* #param mixed $options
*/
public function setOptions($options)
{
$this->options[] = $options;
return $this;
}
/**
* #return mixed
*/
public function getOptions()
{
return $this->options;
}
function __toString()
{
return $this->getQuestionText();
}
/**
* #param boolean $expanded
*/
public function setExpanded($expanded)
{
$this->expanded = $expanded;
}
/**
* #return boolean
*/
public function getExpanded()
{
return $this->expanded;
}
/**
* #param boolean $multiple
*/
public function setMultiple($multiple)
{
$this->multiple = $multiple;
}
/**
* #return boolean
*/
public function getMultiple()
{
return $this->multiple;
}
/**
* #param \Me\UserBundle\Entity\Questionnaire $questionnaire
*/
public function setQuestionnaire($questionnaire)
{
$this->questionnaire = $questionnaire;
}
/**
* #return \Me\UserBundle\Entity\Questionnaire
*/
public function getQuestionnaire()
{
return $this->questionnaire;
}
}
and
<?php
namespace Me\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* QuestionOption
*
* #ORM\Table(name="option")
* #ORM\Entity(repositoryClass="Me\UserBundle\Entity\OptionRepository")
*/
class Option
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="questionId", type="integer")
*/
private $questionId;
/**
* #var string
*
* #ORM\Column(name="optionText", type="string", length=255)
*/
private $optionText;
/**
* #ORM\ManyToOne(targetEntity="Question", inversedBy="options")
* #ORM\JoinColumn(name="questionId", referencedColumnName="id", onDelete="cascade")
**/
private $question;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set optionText
*
* #param string $optionText
* #return Option
*/
public function setOptionText($optionText)
{
$this->optionText = $optionText;
return $this;
}
/**
* Get optionText
*
* #return string
*/
public function getOptionText()
{
return $this->optionText;
}
/**
* #return mixed
*/
public function getQuestion()
{
return $this->question;
}
/**
* #param mixed $question
*/
public function setQuestion($question)
{
$this->question = $question;
}
/**
* #param int $id
*/
public function setId($id)
{
$this->id = $id;
}
function __toString()
{
return $this->getOptionText();
}
}
I also have a questionnaire entity, though I don't think I really need it because users won't be creating questionnaires, only filling the single questionnaire during registration.
My user entity:
<?php
namespace Me\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="Me\UserBundle\Entity\UserRepository")
*/
class User
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="firstName", type="string", length=50)
*/
private $firstName;
/**
* #var string
*
* #ORM\Column(name="middleInitial", type="string", length=50)
*/
private $middleInitial;
/**
* #var string
*
* #ORM\Column(name="lastName", type="string", length=50)
*/
private $lastName;
/**
* #var string
*
* #ORM\Column(name="homePhoneArea", type="string", length=3)
*/
private $homePhoneArea;
/**
* #var string
*
* #ORM\Column(name="homePhoneNumber", type="string", length=7)
*/
private $homePhoneNumber;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=50)
*/
private $email;
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*/
public $questions;
public function __construct()
{
$this->questions = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set firstName
*
* #param string $firstName
* #return User
*/
public function setFirstName($firstName)
{
$this->firstName = $firstName;
return $this;
}
/**
* Get firstName
*
* #return string
*/
public function getFirstName()
{
return $this->firstName;
}
/**
* Set middleInitial
*
* #param string $middleInitial
* #return User
*/
public function setMiddleInitial($middleInitial)
{
$this->middleInitial = $middleInitial;
return $this;
}
/**
* Get middleInitial
*
* #return string
*/
public function getMiddleInitial()
{
return $this->middleInitial;
}
/**
* Set lastName
*
* #param string $lastName
* #return User
*/
public function setLastName($lastName)
{
$this->lastName = $lastName;
return $this;
}
/**
* Get lastName
*
* #return string
*/
public function getLastName()
{
return $this->lastName;
}
/**
* Set homePhoneArea
*
* #param string $homePhoneArea
* #return User
*/
public function setHomePhoneArea($homePhoneArea)
{
$this->homePhoneArea = $homePhoneArea;
return $this;
}
/**
* Get homePhoneArea
*
* #return string
*/
public function getHomePhoneArea()
{
return $this->homePhoneArea;
}
/**
* Set homePhoneNumber
*
* #param string $homePhoneNumber
* #return User
*/
public function setHomePhoneNumber($homePhoneNumber)
{
$this->homePhoneNumber = $homePhoneNumber;
return $this;
}
/**
* Get homePhoneNumber
*
* #return string
*/
public function getHomePhoneNumber()
{
return $this->homePhoneNumber;
}
/**
* 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;
}
/**
* #return \Doctrine\Common\Collections\ArrayCollection
*/
public function getQuestions()
{
return $this->questions;
}
}
My user controller:
public function newAction()
{
$user = new User();
$em = $this->getDoctrine()->getManager();
$questions = $em->getRepository('MeUserBundle:Question')->findAll();
if (!$questions) {
throw $this->createNotFoundException('Unable to find Questions.');
}
$builder = $this->createFormBuilder();
$optionEntities = array();
foreach ($questions as $question)
{
$options = array();
foreach ($question->getOptions() as $option)
{
$options[$option->getId()] = $option->getOptionText();
$optionEntities[$option->getId()] = $option;
}
$builder->add('question_'. $question->getId(), 'choice', array(
'label' => $question->getQuestionText(),
'expanded' => $question->getExpanded(),
'multiple' => $question->getMultiple(),
'choices' => $options
));
}
$user->getQuestions()->add($questions);
$form = $this->createForm(new MyFormType(), array('User' => $user));
return $this->render('MeUserBundle:User:new.html.twig', array(
'entity' => $user,
'form' => $form->createView(),
));
}
The form type as it stands today:
<?php
namespace Me\UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class MyFormType extends AbstractType
{
protected $questions;
public function __construct( $questions)
{
$this->questions = $questions;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('questions', 'collection', array(
'type' => new QuestionType()
))
->add('firstName')
->add('middleInitial')
->add('lastName')
->add('homePhoneArea')
->add('homePhoneNumber')
->add('email')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
));
}
public function getName()
{
return 'myform_type';
}
}
This setup doesn't work to get the questions and their associated options, and display them in the same user creation form. I've seen instructions and docs for combining forms, but not creating forms with this kind of configuration. Any guidance would be appreciated.

I'm not sure if I've understood your question correctly but maybe this could help.
From what I see you're building the form(for questions) but you're not using it anywhere! The easiest way is to pass the questions(in your case $user->getQuestions() ) to the MyFormType and the add all the questions inside of the type.
So it would look like something like this
$this->createForm(new MyFormType($user->getQuestions()), array('User' => $user));
And inside your type
protected $questions;
public function __construct($questions)
{
$this->questions = $questions;
}
protected $questions;
public function __construct($questions)
{
$this->questions = $questions;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
foreach ($this->questions as $question)
{
$options = array();
foreach ($question->getOptions() as $option)
{
$options[$option->getId()] = $option->getOptionText();
$optionEntities[$option->getId()] = $option;
}
$builder->add('question_'. $question->getId(), 'choice', array(
'label' => $question->getQuestionText(),
'expanded' => $question->getExpanded(),
'multiple' => $question->getMultiple(),
'choices' => $options
));
}
}
Edit 1
Why don't you try the following?
Add the method setQuestionnaire in User and create a type called QuestionnaireType which is responsible to create the whole questionnaire
In the UserType(sorry for the wrong names) add the QuestionnaireType as an embedded form
Once the user submits the data and you call the bind symfony will pass the whole questionnaire object to the created method so you can iterate over it and save the user's aswers!

Your users entity needs a relation to his $answers you should store in an $answers-field in your user entity, (look up "embedding collections")
Then in your controller that digests the form your store the values by $user->setAnswers(value)) and then you'll find the answers values in the users entity's $answers field ($user->getAnswers()).
ANd dont forget to add your getters and setters.
$php app/console doctrine:generate:entities BundleName:Entityname

At first you could add a setQuestions method in user, this method will receive an ArrayCollection.
Then have you got a look at http://symfony.com/doc/current/reference/forms/types/collection.html ?
And maybe you could ask yourself what does this form should display/do
Does it need to embbed a collection or a list of QuestionFormType could be ok?
Each time i have to do embedded form type, i draw sketches and activity diagram for being sure to not dive into a to complex form structure

Related

One to One Relationship and compound forms (Symfony 3.4)

I have 2 entities, Exercise and Product, they have a One to One relationship (the owning side is Product), and I have an ExerciseFormType and a ProductFormType.
What I want I to be able to create an exercise, and the product associated with it at the same time.
My idea was to add the the builder of exerciseFormType, 'product' and its type would be a ProductFormType. The problem is that the product needs the exercise_id, and the exercise isn't persisted yet so it doesn't have one. Here's what I have so far (it works only for creating a product when the exercise exists).
class ExerciseType extends AbstractType {
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('name')
->add('content')
->add('language')
->add('level')
->add('skillsRequired')
->add('skillsTargetted')
->add('tags')
->add('product', ProductType::class, array(
'required' => false,
'exercise'=> $builder->getData()
)
);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver){
$resolver->setDefaults(array(
'data_class' => 'SchoolBundle\Entity\Exercise'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix(){
return 'schoolbundle_exercise';
}
class ProductType extends AbstractType {
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options){
$builder->add('visibility')->add('price', MoneyType::class);
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$product = $event->getData();
$form = $event->getForm();
$field = (!$product || null === $product->getId()) ? 'publicationDate' : 'updateDate';
$form->add($field, DateTimeType::class, array('data' => new \DateTime()));
});
$data = array(
'data' => $options['exercise'],
'class' => Exercise::class,
'choice_label' => 'getName'
);
$builder->add('exercise', EntityType::class, $data);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver){
$resolver->setDefaults(array(
'data_class' => 'MarketBundle\Entity\Product'
));
$resolver->setRequired(array(
'exercise'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix(){
return 'marketbundle_product';
}
}
In exercise I have that
<?php
/**
* exercise
*
* #ORM\Table(name="exercise")
* #ORM\Entity(repositoryClass="SchoolBundle\Repository\ExerciseRepository")
*/
class Exercise {
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var string
* #ORM\Column(name="content", type="string", length=255)
*/
private $content;
/**
* #var string
* #ORM\Column(name="language", type="string", length=255)
*/
private $language;
/**
* #var int
* #ORM\Column(name="level", type="integer")
*/
private $level;
/**
* #var string
* #ORM\Column(name="skills_required", type="string", length=255)
*/
private $skillsRequired;
/**
* #var string
* #ORM\Column(name="skills_targetted", type="string", length=255)
*/
private $skillsTargetted;
/**
* #var string
* #ORM\Column(name="tags", type="string", length=255)
*/
private $tags;
/**
* #ORM\OneToMany(targetEntity="Session", mappedBy="exercise")
*/
private $sessions;
/**
* #ORM\OneToMany(targetEntity="ExerciseIO", mappedBy="exercise")
*/
private $exerciseIOs;
/**
* #ORM\OneToOne(targetEntity="MarketBundle\Entity\Product", mappedBy="exercise", cascade={"persist"}))
*/
private $product;
/**
* #ORM\ManyToOne(targetEntity="Professor", inversedBy="createdExercises")
* #ORM\JoinColumn(name="creator_id", referencedColumnName="id", nullable=false)
*/
private $creator;
/**
* #ORM\ManyToMany(targetEntity="Professor", mappedBy="boughtExercises")
*/
private $owners;
public function __construct(){
$this->sessions = new ArrayCollection();
$this->exerciseIOs = new ArrayCollection();
$this->owners = new ArrayCollection();
}
/**
* Get creator
* #return Professor
*/
public function getCreator(){
return $this->creator;
}
/**
* Set creator
* #param Professor $creator
* #return Exercise
*/
public function setCreator($creator){
$this->creator = $creator;
return $this;
}
/**
* Get owner
* #return ArrayCollection
*/
public function getOwners(){
return $this->owners;
}
/**
* Get product
* #return Product
*/
public function getProduct(){
return $this->product;
}
/**
* #param Product $product
* #return Exercise
*/
public function setProduct($product){
$this->product = $product;
return $this;
}
/**
* Get exerciseIOs
* #return ArrayCollection
*/
public function getExerciseIOs(){
return $this->exerciseIOs;
}
/**
* Get sessions
* #return ArrayCollection
*/
public function getSessions(){
return $this->sessions;
}
/**
* Get id
* #return int
*/
public function getId(){
return $this->id;
}
/**
* Set name
* #param string $name
* #return Exercise
*/
public function setName($name){
$this->name = $name;
return $this;
}
/**
* Get name
* #return string
*/
public function getName(){
return $this->name;
}
/**
* Set content
* #param string $content
* #return Exercise
*/
public function setContent($content){
$this->content = $content;
return $this;
}
/**
* Get content
* #return string
*/
public function getContent(){
return $this->content;
}
/**
* Set language
* #param string $language
* #return Exercise
*/
public function setLanguage($language){
$this->language = $language;
return $this;
}
/**
* Get language
* #return string
*/
public function getLanguage(){
return $this->language;
}
/**
* Set level
* #param string $level
* #return Exercise
*/
public function setLevel($level){
$this->level = $level;
return $this;
}
/**
* Get level
* #return string
*/
public function getLevel(){
return $this->level;
}
/**
* Set skillsRequired
* #param string $skillsRequired
* #return Exercise
*/
public function setSkillsRequired($skillsRequired){
$this->skillsRequired = $skillsRequired;
return $this;
}
/**
* Get skillsRequired
* #return string
*/
public function getSkillsRequired(){
return $this->skillsRequired;
}
/**
* Set skillsTargetted
* #param string $skillsTargetted
* #return Exercise
*/
public function setSkillsTargetted($skillsTargetted){
$this->skillsTargetted = $skillsTargetted;
return $this;
}
/**
* Get skillsTargetted
* #return string
*/
public function getSkillsTargetted(){
return $this->skillsTargetted;
}
/**
* Set tags
* #param string $tags
* #return Exercise
*/
public function setTags($tags){
$this->tags = $tags;
return $this;
}
/**
* Get tags
* #return string
*/
public function getTags(){
return $this->tags;
}
}
And in Product
/**
* Product
*
* #ORM\Table(name="product")
* #ORM\Entity(repositoryClass="\MarketBundle\Repository\ProductRepository")
*/
class Product {
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var bool
* #ORM\Column(name="visibility", type="boolean")
*/
private $visibility;
/**
* #var float
* #ORM\Column(name="price", type="float")
*/
private $price;
/**
* #var \DateTime
* #ORM\Column(name="publication_date", type="datetimetz")
*/
private $publicationDate;
/**
* #var \DateTime
* #ORM\Column(name="update_date", type="datetimetz", nullable=true)
*/
private $updateDate;
/**
* #ORM\OneToMany(targetEntity="ProductComment", mappedBy="product")
*/
private $productComments;
/**
* #ORM\OneToOne(targetEntity="\SchoolBundle\Entity\Exercise", inversedBy="product")
* #ORM\JoinColumn(name="exercise_id", referencedColumnName="id", nullable=false)
*/
private $exercise;
public function __construct(){
$this->productComments = new ArrayCollection();
}
/**
* Get exercise
* #return Exercise
*/
public function getExercise(){
return $this->exercise;
}
/**
* Set exercise
* #param Exercise $exercise
* #return Product
*/
public function setExercise($exercise){
$this->exercise = $exercise;
return $this;
}
/**
* Get productComments
* #return ArrayCollection
*/
public function getProductComments(){
return $this->productComments;
}
/**
* Get id
* #return int
*/
public function getId(){
return $this->id;
}
/**
* Set visibility
* #param boolean $visibility
* #return Product
*/
public function setVisibility($visibility){
$this->visibility = $visibility;
return $this;
}
/**
* Get visibility
* #return bool
*/
public function getVisibility(){
return $this->visibility;
}
/**
* Set price
* #param float $price
* #return Product
*/
public function setPrice($price){
$this->price = $price;
return $this;
}
/**
* Get price
* #return float
*/
public function getPrice(){
return $this->price;
}
/**
* Set publicationDate
* #param \DateTime $publicationDate
* #return Product
*/
public function setPublicationDate($publicationDate){
$this->publicationDate = $publicationDate;
return $this;
}
/**
* Get publicationDate
* #return \DateTime
*/
public function getPublicationDate(){
return $this->publicationDate;
}
/**
* Set updateDate
* #param \DateTime $updateDate
* #return Product
*/
public function setUpdateDate($updateDate){
$this->updateDate = $updateDate;
return $this;
}
/**
* Get updateDate
* #return \DateTime
*/
public function getUpdateDate(){
return $this->updateDate;
}
}
I've said it works for an existing exercise (and no product).
When I try to create both at the same time I get
Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
It's probably from the $builder->getData(), because in that case I only passed to the form a "new Exercice()". Here's the controller action
public function newAction(Request $request){
$exercise = new Exercise();
$form = $this->createForm(ExerciseType::class, $exercise);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$exercise->setCreator($this->getUser());
$em = $this->getDoctrine()->getManager();
$em->persist($exercise);
$em->flush();
return $this->redirectToRoute('exercise_show', array('id' => $exercise->getId()));
}
(Also this is another question but when I disable a formType, it is rendered, and the value appears but it's not submitted. I would actually prefer a hiddenFormType but I need the formatting of the DateTimeFormType)
Ok, this is the solution I've made once with Symfony2.8, I hope it can helps you.
/**
* #ORM\Entity
* #ORM\Table(name="picture")
*/
class Picture
{
/**
* #ORM\OneToOne(targetEntity="AppBundle\Entity\Host",
* inversedBy="pictureId"
* )
* #ORM\JoinColumn(name="avatar_host_id", referencedColumnName="id", nullable=true)
*/
private $avatarHostId;
}
/**
* #ORM\Entity
* #ORM\Table(name="host")
*/
class Host
{
/**
* #ORM\OneToOne(targetEntity="AppBundle\Entity\Picture",
* mappedBy="avatarHostId", cascade={"persist", "remove", "merge"}
* )
*/
private $pictureId;
}
class HostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('pictureId', PictureFileType::class);
}
}
class PictureFileType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('assetFile', FileType::class, array(
'label' => 'Picture File',
'required' => false,
'validation_groups' => array('creation')
));
}
}
First, I recommend moving away from using integers as IDs. There are some issues around them, including that you can't really generate one at will in this kind of scenario. I would recommend Uuids along with ramsey/uuid, which also has a Doctrine mapping.
When you've got a situation where you need an ID before it's been persisted and the Uuid generated, generate the Uuid yourself. For instance, in a contrived example
class Order
{
/**
* #var UuidInterface
*
* #ORM\Id
* #ORM\Column(type="uuid")
* #ORM\GeneratedValue(strategy="NONE")
* #ORM\CustomIdGenerator(class=UuidGenerator::class)
*/
private $id;
...
/**
* Constructor.
*
* #param UuidInterface $id
*/
public function __construct(?UuidInterface $id = null)
{
$this->id = $id ?? Uuid::uuid4();
}
...
}
class OrderController
{
...
public function orderProductAction(): JsonResponse
{
...
// We need this ahead of time, because
// maybe this is Async and we need to
// return the order id. This happens a
// lot with commands.
$generatedId = Uuid::uuid4();
// Here it's going to use the given ID,
// if not given, the Order class will
// generate it.
$order = new Order($generatedId, ...);
// Stuff happens, persisted... maybe we
// don't have the persisted Order object...
return $this->json([
'order' => [
'id' => $generatedId->toString(),
],
]);
}
...
}
The meat of it is providing the generated Uuid in the constructor (which alternately generates it if null). Do not add a setter. Here's a more involved example:
public function createAction(Request $request): JsonResponse
{
$request_data = \json_decode($request->getContent(), true);
$tenant_data = $request_data['data'];
// Pre-generate our Uuid for the Tenant.
$generated_id = Uuid::uuid4();
/** #var CreateTenant $create_tenant_cmd */
$create_tenant_cmd = new CreateTenant($generated_id);
$create_tenant_cmd->setName($tenant_data['name']);
$create_tenant_cmd->setDomainName($tenant_data['domain_name']);
$create_tenant_cmd->setOwnerUsername($tenant_data['owner_username']);
$create_tenant_cmd->setOwnerPassword($tenant_data['owner_password']);
$create_tenant_cmd->setOwnerFirstName($tenant_data['owner_first_name']);
$create_tenant_cmd->setOwnerLastName($tenant_data['owner_last_name']);
$create_tenant_cmd->setOwnerEmail($tenant_data['owner_email']);
if (!$this->isGranted('perform', $create_tenant_cmd)) {
throw new AccessDeniedException('Access denied to create tenant.');
}
// Here, we should expect NO side-effects, the command
// can't return anything. So no Tenant object with
// generated Uuid...
$this->get('command_bus')->handle($create_tenant_cmd);
/* #var Serializer $serializer */
$serializer = $this->get('jms_serializer');
$serializer_context = SerializationContext::create()->setGroups([
'tenant_meta',
]);
$tenant = $this->get('app.repository.tenant')->find($generated_id);
return $this->json(\json_decode($serializer->serialize(
$tenant,
'json',
$serializer_context
)));
}
That's the ID question; the second part of your question is now easily resolved, that being giving the Uuid to the FormType instead:
$form = $this->createForm(OrderProductType::class, $product, [
'product' => $product,
'generatedId' => $generatedId,
]);
class OrderProductType extends AbstractType implements DataMapperInterface
{
/** #var UuidInterface */
protected $generatedId;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->generatedId = $options['generatedId'];
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setDefaults([
'data_class' => OrderProduct::class,
])
->setRequired(['generatedId'])
;
}
public function mapFormsToData($forms, &$data)
{
$forms = iterator_to_array($forms);
$data = new OrderProduct($this->generatedId);
...
}
}
Of course, if you need it as a field, use it with the field type of your choice instead of storing it as a variable, and then get it from that field:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('product_id', HiddenType::class, [
'product_id' => $options['generatedId']->toString(),
])
...
;
}
public function mapFormsToData($forms, &$data)
{
$forms = iterator_to_array($forms);
// Note use of Uuid::fromString().
$data = new OrderProduct(Uuid::fromString(
$forms['productId']->getData()
));
...
}
This is one of the downsides of not delegating the process of interaction to a delegate object like a command, instead of generating an entity; you're stuck constructing your object before you need it, in whole, or perverting the design to make it fit. It also makes working with assertions harder as well (you only get one set, the entity's).

Symfony Catchable Fatal Error: Object of class DataBundle\Entity\Location could not be converted to string

I am trying to create a little CRUD system with 2 entities and a OneToMany relationship between these 2 entities.
My entities are Location & Job. I created the entities and created the crud controller via doctrine for both.
Location CRUD works great but Job only Read & Delete works. When I try to create a new Job it throws the following exception:
Catchable Fatal Error: Object of class DataBundle\Entity\Location
could not be converted to string
I have no idea what it means or what is causing it.
If anyone could help me out that would be realy awesome!
Many thanks in advance!
Here is my code.
Entities:
Location
<?php
namespace DataBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Location
*
* #ORM\Table(name="location")
* #ORM\Entity(repositoryClass="DataBundle\Repository\LocationRepository")
*/
class Location
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="street", type="string", length=255)
*/
private $street;
/**
* #var string
*
* #ORM\Column(name="number", type="string", length=25)
*/
private $number;
/**
* #var string
*
* #ORM\Column(name="postalcode", type="string", length=4)
*/
private $postalcode;
/**
* #var string
*
* #ORM\Column(name="city", type="string", length=255)
*/
private $city;
/**
* #var Job[] Available jobs for this location.
*
* #ORM\OneToMany(targetEntity="Job", mappedBy="location")
*/
private $jobs;
public function __construct()
{
$this->jobs = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Location
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set street
*
* #param string $street
*
* #return Location
*/
public function setStreet($street)
{
$this->street = $street;
return $this;
}
/**
* Get street
*
* #return string
*/
public function getStreet()
{
return $this->street;
}
/**
* Set number
*
* #param string $number
*
* #return Location
*/
public function setNumber($number)
{
$this->number = $number;
return $this;
}
/**
* Get number
*
* #return string
*/
public function getNumber()
{
return $this->number;
}
/**
* Set postalcode
*
* #param string $postalcode
*
* #return Location
*/
public function setPostalcode($postalcode)
{
$this->postalcode = $postalcode;
return $this;
}
/**
* Get postalcode
*
* #return string
*/
public function getPostalcode()
{
return $this->postalcode;
}
/**
* Set city
*
* #param string $city
*
* #return Location
*/
public function setCity($city)
{
$this->city = $city;
return $this;
}
/**
* Get city
*
* #return string
*/
public function getCity()
{
return $this->city;
}
/**
* Add job
*
* #param \DataBundle\Entity\Job $job
*
* #return Location
*/
public function addJob(\DataBundle\Entity\Job $job)
{
$this->jobs[] = $job;
return $this;
}
/**
* Remove job
*
* #param \DataBundle\Entity\Job $job
*/
public function removeJob(\DataBundle\Entity\Job $job)
{
$this->jobs->removeElement($job);
}
/**
* Get jobs
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getJobs()
{
return $this->jobs;
}
}
Job:
<?php
namespace DataBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Job
*
* #ORM\Table(name="job")
* #ORM\Entity(repositoryClass="DataBundle\Repository\JobRepository")
*/
class Job
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=255)
*/
private $description;
/**
* #var Location
*
* #ORM\ManyToOne(targetEntity="Location", inversedBy="jobs")
* #ORM\JoinColumn(name="location_id", referencedColumnName="id")
*/
private $location;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
*
* #return Job
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set description
*
* #param string $description
*
* #return Job
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set location
*
* #param \DataBundle\Entity\Location $location
*
* #return Job
*/
public function setLocation(\DataBundle\Entity\Location $location = null)
{
$this->location = $location;
return $this;
}
/**
* Get location
*
* #return \DataBundle\Entity\Location
*/
public function getLocation()
{
return $this->location;
}
}
My new action in the JobController:
/**
* Creates a new job entity.
*
*/
public function newAction(Request $request)
{
$job = new Job();
$form = $this->createForm('DataBundle\Form\JobType', $job);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($job);
$em->flush($job);
return $this->redirectToRoute('job_show', array('id' => $job->getId()));
}
return $this->render('job/new.html.twig', array(
'job' => $job,
'form' => $form->createView(),
));
}
DataBundle/Form/JobTypep
<?php
namespace DataBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class JobType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('title')->add('description')->add('location') ;
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'DataBundle\Entity\Job'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'databundle_job';
}
}
You can't use location as text field in your form, location is object.
You can fix this error by using form data transformers that will convert location into text on form output and text in location object on form submit.
http://symfony.com/doc/current/form/data_transformers.html
Or by using form type EnityType for location:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('title')->add('description');
$builder
->add('location', Symfony\Bridge\Doctrine\Form\Type\EntityType::class, [
'required' => false,
'expanded' => false,
'multiple' => false,
'class' => 'DataBundle\\Entity\\Location',
'empty_data' => '',
'choice_label' => 'name',
'label' => 'Location',
]);
}
http://symfony.com/doc/current/reference/forms/types/entity.html

Cannot get related entity field to save in Symfony Admin Form

I'm working my way through Symfony trying to learn how it all fits together and I'm working on the admin section.
Right now I'm putting together an admin form for a Show Entity which will reference a section entity (so this show belongs in that section, etc). Every other field in the form saves EXCEPT for the related entity choice field.
This is the ShowAdmin class
<?php
namespace AppBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Nelmio\ApiDocBundle\Tests\Fixtures\Form\EntityType;
class ShowAdmin extends AbstractAdmin {
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('title', 'text')
->add('shortname', 'text')
->add('section_id', EntityType::class, array(
'class' => 'AppBundle:SectionEntity',
'choice_label' => 'section_title',
))
->add('logo', 'text')
->add('description', 'textarea')
->add('status', 'integer');
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper->add('title');
$datagridMapper->add('shortname');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('title');
$listMapper->add('shortname', 'text');
}
}
This is the ShowEntity
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="shows")
*/
class ShowEntity {
function __construct() {
$this->children = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=100)
*/
private $title;
/**
* #ORM\Column(type="string", length=100)
*/
private $shortname;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\SectionEntity")
*/
private $section;
/**
* #ORM\Column(type="string", length=255)
*/
private $logo;
/**
* #ORM\Column(type="text")
*/
private $description;
/**
* #ORM\Column(type="integer")
*/
private $status;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
*
* #return ShowEntity
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set sectionId
*
* #param integer $sectionId
*
* #return ShowEntity
*/
public function setSectionId($sectionId)
{
$this->section_id = $sectionId;
return $this;
}
/**
* Get sectionId
*
* #return integer
*/
public function getSectionId()
{
return $this->section_id;
}
/**
* Set logo
*
* #param string $logo
*
* #return ShowEntity
*/
public function setLogo($logo)
{
$this->logo = $logo;
return $this;
}
/**
* Get logo
*
* #return string
*/
public function getLogo()
{
return $this->logo;
}
/**
* Set description
*
* #param string $description
*
* #return ShowEntity
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set status
*
* #param integer $status
*
* #return ShowEntity
*/
public function setStatus($status)
{
$this->status = $status;
return $this;
}
/**
* Get status
*
* #return integer
*/
public function getStatus()
{
return $this->status;
}
/**
* Set shortname
*
* #param string $shortname
*
* #return ShowEntity
*/
public function setShortname($shortname)
{
$this->shortname = $shortname;
return $this;
}
/**
* Get shortname
*
* #return string
*/
public function getShortname()
{
return $this->shortname;
}
}
And this is the SectionEntity
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* SectionEntity
*
* #ORM\Table(name="section_entity")
* #ORM\Entity(repositoryClass="AppBundle\Repository\SectionEntityRepository")
*/
class SectionEntity
{
protected $section_id;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="text")
*/
private $section_title;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set sectionTitle
*
* #param string $sectionTitle
*
* #return SectionEntity
*/
public function setSectionTitle($sectionTitle)
{
$this->section_title = $sectionTitle;
return $this;
}
/**
* Get sectionTitle
*
* #return string
*/
public function getSectionTitle()
{
return $this->section_title;
}
/**
* Get string
*/
public function __toString() {
return $this->section_title;
}
function __construct() {
$this->section_id = new \Doctrine\Common\Collections\ArrayCollection();
}
}
Any help would be greatly appreciated, I know it's probably something super simple that I'm just not seeing.
Thanks.
(optional) Rename ShowEntity::$section into ShowEntity::$sections to highlight sections is a collection but not a single entity.
Set ShowEntity __construct method body to:
$this->sections = new \Doctrine\Common\Collections\ArrayCollection();
At ShowAdmin::configureFormFields rename
->add('section_id', EntityType::class, array(
into
->add('section', EntityType::class, array(
You should use direct reference to the relation instead of id.
Remove SectionEntity::__construct method, it has no sense.
Remove protected $section_id; from SectionEntity.
Change public function setSectionId($sectionId) into public function setSection(Section $section).
Perhaps you also need to rename section_title into sectionTitle or simply title, not sure about that.

Data Transformer for Collection Field Type

I am creating a Chat system. I have two entities Chat and ChatThread.
namespace Acme\UitBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Chat
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Acme\UitBundle\Entity\ChatRepository")
* #ORM\HasLifecycleCallbacks()
*/
class Chat
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="chats")
* #ORM\JoinColumn(name="uid", referencedColumnName="id")
*/
private $user;
/**
* #var string
*
* #ORM\Column(name="msg", type="text")
*/
private $msg;
/**
* #ORM\ManyToOne(targetEntity="ChatThread", inversedBy="chats")
* #ORM\JoinColumn(name="tid", referencedColumnName="id")
*/
private $thread;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime")
*/
private $date;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set user
*
* #param \stdClass $user
* #return Chat
*/
public function setUser($user)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \stdClass
*/
public function getUser()
{
return $this->user;
}
/**
* Set msg
*
* #param string $msg
* #return Chat
*/
public function setMsg($msg)
{
$this->msg = $msg;
return $this;
}
/**
* Get msg
*
* #return string
*/
public function getMsg()
{
return $this->msg;
}
/**
* Set date
*
* #param \DateTime $date
* #return Chat
*/
public function setDate($date)
{
$this->date = $date;
return $this;
}
/**
* Get date
*
* #return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* #ORM\PrePersist
*/
public function setDateValue()
{
$this->date = new \DateTime();
}
/**
* Set thread
*
* #param \Acme\UitBundle\Entity\ChatThread $thread
* #return Chat
*/
public function setThread(\Acme\UitBundle\Entity\ChatThread $thread = null)
{
$this->thread = $thread;
return $this;
}
/**
* Get thread
*
* #return \Acme\UitBundle\Entity\ChatThread
*/
public function getThread()
{
return $this->thread;
}
}
Entity ChatThread :
namespace Acme\UitBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\OrderBy;
use Doctrine\Common\Collections\ArrayCollection;
/**
* ChatThread
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Acme\UitBundle\Entity\ChatThreadRepository")
*/
class ChatThread
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToMany(targetEntity="User", inversedBy="inside")
*/
private $inside;
/**
* #ORM\OneToMany(targetEntity="Chat", mappedBy="thread")
* #OrderBy({"date" = "DESC"})
*/
private $chats;
public function __construct()
{
$this->chats=new ArrayCollection();
$this->inside=new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set inside
*
* #param array $inside
* #return ChatThread
*/
public function setInside($inside)
{
$this->inside = $inside;
return $this;
}
/**
* Get inside
*
* #return array
*/
public function getInside()
{
return $this->inside;
}
/**
* Add inside
*
* #param \Acme\UitBundle\Entity\User $inside
* #return ChatThread
*/
public function addInside(\Acme\UitBundle\Entity\User $inside)
{
$this->inside[] = $inside;
return $this;
}
/**
* Remove inside
*
* #param \Acme\UitBundle\Entity\User $inside
*/
public function removeInside(\Acme\UitBundle\Entity\User $inside)
{
$this->inside->removeElement($inside);
}
/**
* Add chats
*
* #param \Acme\UitBundle\Entity\Chat $chats
* #return ChatThread
*/
public function addChat(\Acme\UitBundle\Entity\Chat $chats)
{
$this->chats[] = $chats;
return $this;
}
/**
* Remove chats
*
* #param \Acme\UitBundle\Entity\Chat $chats
*/
public function removeChat(\Acme\UitBundle\Entity\Chat $chats)
{
$this->chats->removeElement($chats);
}
/**
* Get chats
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getChats()
{
return $this->chats;
}
}
What I want to do is Take users to be added in inside and create a ChatThread and add a msg in Chat.
I have a form of chatType which takes user id's as collection with name thread. I have used a data transformer to transform inside into ChatThread.
namespace Acme\UitBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Acme\UitBundle\Form\DataTransformer\ThreadToInsideTransformer;
class ChatType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$entityManager = $options['em'];
$transformer = new ThreadToInsideTransformer($entityManager);
$builder->add(
$builder->create('thread', 'collection' ,array('allow_add' => true,'label' => false))->addModelTransformer($transformer)
);
$builder->add('msg','textarea');
/* $builder->add('inside','collection',array(
'allow_add' => true,
'allow_delete' => true)); */
$builder->add('hook', 'submit');
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'Acme\UitBundle\Entity\Chat'
))
->setRequired(array(
'em',
))
->setAllowedTypes(array(
'em' => 'Doctrine\Common\Persistence\ObjectManager',
));
}
public function getName() {
return 'chat';
}
}
data transformer
namespace Acme\UitBundle\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Acme\UitBundle\Entity\ChatThread;
class ThreadToInsideTransformer implements DataTransformerInterface
{
/**
* #var ObjectManager
*/
private $om;
/**
* #param ObjectManager $om
*/
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
/**
* Transforms an object (thread) to an array (inside).
*
* #param Thread $thread
* #return array
*/
public function transform($thread)
{
if (null === $thread) {
return "";
}
return $thread->getInside();
}
/**
* Transforms a array (inside) to an object (thread).
*
* #param array $inside
*
* #return Thread
*
* #throws Create new Thread if object (thread) is not found.
*/
public function reverseTransform($inside)
{
if (!is_array($inside)) {
return null;
}
$a=$this->om
->getRepository('AcmeUitBundle:User')
->findById($inside);
if (null === $a) {
throw new TransformationFailedException(sprintf(
'Error. . .'
));
}
$thread = $this->om
->getRepository('AcmeUitBundle:ChatThread')
->findByInsideChat($a)
;
if (null === $thread) {
$thread=new ChatThread();
$thread->setInside($inside);
$this->om->persist($thread);
$this->om->flush();
}
return $thread;
}
}
When I submit form, I get this error Expected argument of type "object, array or empty", "string" given.

symfony2 selected option

I'm making the user edit.
I want to view selected role of the current user by Users.role_id = UsersRole.id
The table Users has four columns (id,username,roleId,descriptions)
The table UsersRole has two columns (id,name)
Controller:
public function editAction($id) {
$user = $this->getDoctrine()
->getEntityManager()
->getRepository('TruckingMainBundle:Users')
->find($id);
if (!$user) {
throw $this->createNotFoundException('Unable to find user id.');
}
$form = $this->createForm(new \Trucking\AdminBundle\Form\UserType(), $user);
$request = $this->getRequest();
//save data
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($user);
$em->flush();
return $this->redirect($this->generateUrl('tracking_admin_users'));
}
}
return $this->render('TruckingAdminBundle:user:edit.html.twig', array(
'id' => $id,
'form' => $form->createView()
)
);
}
UserType.php
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('roleId', 'entity', array(
'class' => 'TruckingMainBundle:UsersRole',
'property' => 'name'
))
->...->..
}
I don't know how to set selected (default) value in that list, I've been trying to do it for 5 hours ,but still no results I've used preferred_choices, query_builder -> where I can select by critreia(but i don't need that)
http://symfony.com/doc/current/reference/forms/types/entity.html
I can print my current user id -> print_r($user->getRoleId()); I already have it.
My 'Users' entity has connection with UserRole entity
Users entity
namespace Trucking\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* Trucking\MainBundle\Entity\Users
*
* #ORM\Table(name="Users")
* #ORM\Entity
*/
class Users implements UserInterface
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #var string $password
*
* #ORM\Column(name="password", type="string", length=15)
*/
private $password;
/**
* #var string $username
*
* #ORM\Column(name="username", type="string", length=30)
*/
private $username;
/**
* #var string $description
*
* #ORM\Column(name="description", type="string", length=20)
*/
private $description;
/**
* #var string $permissions
*
* #ORM\Column(name="permissions", type="string", length=300)
*/
private $permissions;
/**
* #var \DateTime $date
*
* #ORM\Column(name="date", type="datetime")
*/
private $date;
/**
* #var integer $role_id
*
* #ORM\Column(name="role_id", type="integer")
*/
private $role_id;
/**
* #var integer $company_id
*
* #ORM\Column(name="company_id", type="integer")
*/
private $company_id;
/**
* #ORM\ManyToMany(targetEntity="Company", inversedBy="users")
*
*/
protected $companies;
/**
* #ORM\OneToOne(targetEntity="UsersRole")
* #ORM\JoinColumn(name="role_id", referencedColumnName="id")
*/
protected $roles;
public function __construct() {
$this->companies = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set password
*
* #param string $password
* #return Users
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set username
*
* #param string $username
* #return Users
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set description
*
* #param string $description
* #return Users
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set permissions
*
* #param string $permissions
* #return Users
*/
public function setPermissions($permissions)
{
$this->permissions = $permissions;
return $this;
}
/**
* Get permissions
*
* #return string
*/
public function getPermissions()
{
return $this->permissions;
}
/**
* Set date
*
* #param \DateTime $date
* #return Users
*/
public function setDate($date)
{
$this->date = $date;
return $this;
}
/**
* Get date
*
* #return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* Set role_id
*
* #param integer $role
* #return Users
*/
public function setRoleId($role_id)
{
$this->roleId = $role_id;
return $this;
}
/**
* Get role_id
*
* #return integer
*/
public function getRoleId()
{
return $this->role_id;
}
/**
* Set company_id
*
* #param Company $company_id
* #return Users
*/
public function setCompany(Company $company_id)
{
$this->company = $company_id;
return $this;
}
/**
* Get company_id
*
* #return integer
*/
public function getCompanyId()
{
return $this->company_id;
}
public function equals(UserInterface $user) {
return $this->getUsername() == $user->getUsername();
}
public function eraseCredentials() {
}
public function getRoles() {
return (array)$this->roles->getName();
}
public function setRoles($role) {
$this->roles = array($role);
}
public function getSalt() {
}
}
UsersRole entity
namespace Trucking\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* USERS_ROLE
*
* #ORM\Table(name="USERS_ROLE")
* #ORM\Entity
*/
class UsersRole
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=30)
*/
protected $name;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=200)
*/
protected $description;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return USERS_ROLE
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set description
*
* #param string $description
* #return USERS_ROLE
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
}
UserType (for form)
<?php
namespace Trucking\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints;
class UserType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add("username","text",array(
"label" => "Name",
'attr' => array(
'class' => 'input-xlarge',
),
'constraints' => new Constraints\Length(array('min' => 3))
))
->add('roleId', 'entity', array(
'class' => 'TruckingMainBundle:UsersRole',
"label" => "Roles",
'property' => 'name'
))
->add("description","text",array(
"label" => "Description",
'attr' => array(
'class' => 'input-xlarge'
),
'constraints' => new Constraints\NotBlank()
));
}
public function getName()
{
return 'trucing_adminbundle_usertype';
}
}
Set the property on your entity before you render the form:
if (!$user) {
throw $this->createNotFoundException('Unable to find user id.');
}
//THIS IS NEW
$theRole = getRoleEntityFromSomewhereItMakesSense();
$user->setRole($theRole); //Pass the role object, not the role's ID
$form = $this->createForm(new \Trucking\AdminBundle\Form\UserType(), $user);
$request = $this->getRequest();
When you generate a form, it gets automatically populated with the properties of the entity you are using.
EDIT
Change
->add('roleId', 'entity', array(
to
->add('roles', 'entity', array(
I don't get why you have roleId and roles at the same time.
Also change the following, since roles is a single element, not an array (you have a relation one-to-one on it, and should be one-to-many and reversed as many-to-one, but I guess it will also work)
public function getRoles() {
return $this->roles;
}
public function setRoles($role) {
$this->roles = $role;
}
There has been a problem with ORM JOINS. id to role_id
I've changed the mapping from One-To-One Bidirectional
to One-To-One, Unidirectional with Join Table.
Full code:
Users.php
<?php
namespace Trucking\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* Trucking\MainBundle\Entity\Users
*
* #ORM\Table(name="Users")
* #ORM\Entity
*/
class Users implements UserInterface
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #var string $password
*
* #ORM\Column(name="password", type="string", length=15)
*/
protected $password;
/**
* #var string $username
*
* #ORM\Column(name="username", type="string", length=30)
*/
protected $username;
/**
* #var string $description
*
* #ORM\Column(name="description", type="string", length=20)
*/
protected $description;
/**
* #var string $permissions
*
* #ORM\Column(name="permissions", type="string", length=300)
*/
protected $permissions;
/**
* #var integer $company_id
*
* #ORM\Column(name="company_id", type="integer")
*/
protected $company_id;
/**
* #var integer $role_id
*
* #ORM\Column(name="role_id", type="integer")
*/
protected $role_id;
/**
* #ORM\OneToOne(targetEntity="Company")
* #ORM\JoinColumn( name="company_id", referencedColumnName="id" )
*/
protected $companies;
/**
* #ORM\OneToOne(targetEntity="UsersRole")
* #ORM\JoinColumn( name="role_id", referencedColumnName="id" )
*/
protected $listRoles;
public function __construct() {
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set password
*
* #param string $password
* #return Users
*/
public function setPassword($password)
{
$this->password = sha1($password);
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set username
*
* #param string $username
* #return Users
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set description
*
* #param string $description
* #return Users
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set permissions
*
* #param string $permissions
* #return Users
*/
public function setPermissions($permissions)
{
$this->permissions = $permissions;
return $this;
}
/**
* Get permissions
*
* #return string
*/
public function getPermissions()
{
return $this->permissions;
}
/**
* Set company_id
*
* #param Company $company_id
* #return Users
*/
public function setCompanyId($company_id)
{
$this->company_id = $company_id;
return $this;
}
/**
* Get company_id
*
* #return integer
*/
public function getCompanyId()
{
return $this->company_id;
}
public function equals(UserInterface $user) {
return $this->getUsername() == $user->getUsername();
}
public function eraseCredentials() {
}
/**
* Get roles
*
* #return String
*/
public function getRoles() {
$roles = $this->getListRoles();
return (array)$roles->getName();
}
/**
* Get roles
*
* #return \UsersRole
*/
public function getListRoles()
{
return $this->listRoles;
}
/**
* Set roles
*
* #param \UsersRole
* #return Users
*/
public function setListRoles($roles)
{
$this->listRoles = $roles;
return $this;
}
/**
* Set role_id
*
* #param integer
* #return Users
*/
public function setRoleID($roleId) {
$this->role_id = $roleId;
return $this;
}
public function getSalt() {
}
/**
* Get company
*
* #return Company
*/
public function getCompanies()
{
return $this->companies;
}
/**
* Set company
*
* #param Company $company
* #return Users
*/
public function setCompanies($company)
{
$this->companies = $company;
return $this;
}
}
UsersRole.php
<?php
namespace Trucking\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* USERS_ROLE
*
* #ORM\Table(name="USERS_ROLE")
* #ORM\Entity
*/
class UsersRole
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=30)
*/
protected $name;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=200)
*/
protected $description;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return USERS_ROLE
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set description
*
* #param string $description
* #return USERS_ROLE
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
}
The controller hasn't been changed
public function editAction($id) {
$user = $this->getDoctrine()
->getEntityManager()
->getRepository('TruckingMainBundle:Users')
->find($id);
if (!$user) {
throw $this->createNotFoundException('Unable to find user id.');
}
$form = $this->createForm(new \Trucking\AdminBundle\Form\UserType(), $user);
$request = $this->getRequest();
//save data
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($user);
$em->flush();
return $this->redirect($this->generateUrl('tracking_admin_users'));
}
}
return $this->render('TruckingAdminBundle:user:edit.html.twig', array(
'id' => $id,
'form' => $form->createView()
)
);
}
UserType.php
<?php
namespace Trucking\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints;
class UserType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add("username","text",array(
"label" => "Name",
'attr' => array(
'class' => 'input-xlarge',
),
'constraints' => new Constraints\Length(array('min' => 3))
))
->add("password","password",array(
"label" => "Password",
'attr' => array(
'class' => 'input-xlarge',
),
'constraints' => new Constraints\Length(array('min' => 3))
))
->add("listRoles","entity",array(
'label' => 'Roles',
'class' => 'TruckingMainBundle:UsersRole' ,
'property' => 'name'
))
->add("companies","entity",array(
'label' => 'Companies',
'class' => 'TruckingMainBundle:Company' ,
'property' => 'name'
))
->add("description","text",array(
"label" => "Description",
'attr' => array(
'class' => 'input-xlarge'
),
'constraints' => new Constraints\NotBlank()
));
}
public function getName()
{
return 'trucking_adminbundle_usertype';
}
}

Categories