I couldn't find any similar questions so here goes:
I have a Many-To-Many relationship between my (order)Flow Entity and my Product Entity, but it doesn't select an <option> in the <select>.
All the Entities has been setup by Symfony itself so the #ORM\ManyToMany etc. should be ok.
My controller has the following line:
$form = $this->createForm(new \FDM\BestilBundle\Type\FlowsType(), $flow)->add('submit', 'submit');
The $flow is populated correctly from the db.
The FlowsType file has amoung many fields the following code:
->add('product', 'collection', [
'type' => new ProductDropdownType(),
'allow_add' => TRUE,
'allow_delete' => TRUE,
'prototype' => TRUE,
'by_reference' => FALSE,
]
)
All fields in the FlowsType are filled out correctly, except the one below.
The ProductDropdownType has the following code:
$builder->add('name', 'entity', [
'class' => 'FDMBestilBundle:Flows',
'property' => 'name',
'by_reference' => false
]);
The number of rows is correct - if I have three rows in my many-to-many sql table it shows three rows. They just aren't selected.
If I change the ProductDropdownType to:
$builder->add('name', 'text');
The data is showing just fine - so the db and everyting is working. Except when I want a collection of <select>...
The relations are the following in the Entities:
In the Flow Entity:
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="FDM\BestilBundle\Entity\Product", inversedBy="flow")
* #ORM\JoinTable(name="productsinflows",
* joinColumns={
* #ORM\JoinColumn(name="flow", referencedColumnName="flowId")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="product", referencedColumnName="productId")
* }
* )
*/
private $product;
In the Product Entity:
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="FDM\BestilBundle\Entity\Flows", mappedBy="product")
*/
private $flow;
Can someone please help me - I'm stuck!
You can use query builder in your form, this is an exemple :
In the query builder, create the SQL query with DQL
->add('espece', 'entity', array(
'class' => 'ADMapecheBundle:Espece',
'property' => 'nom',
'multiple' => false,
'query_builder' => function(EspeceRepository $er) use ($user) {
return $er->createQueryBuilder('p')
->where("p.user = :user")
->orderBy('p.nom', 'ASC')
->setParameter('user', $user);
I hope to help you, friendly
Related
I currently have a working form in Symfony where I have a list of companies with checkboxes next to each company name. This is so you can check off which company is assigned to each user. The checkbox currently shows the accountID but it would also be helpful to have the entity field 'name' as well. Can you build a property with two entity fields? Here is my form in my controller:
->add('companies', 'entity', array(
'label' => 'Company',
'class' => 'Default\Bundle\Entity\Customer',
'property' => 'accountId', //This puts the company id next to the check box
'multiple' => true,
'expanded' => true,
'query_builder' => function ($repository)
{
return $repository->createQueryBuilder('c')->orderBy('c.accountId', 'ASC');
},))
->add('Save', 'submit')
->getForm();
This is what I am trying to do:
->add('companies', 'entity', array(
'label' => 'Company',
'class' => 'Default\Bundle\Entity\Customer',
'property' => 'accountId' + 'name', // I want to combine my entity fields here
'multiple' => true,
'expanded' => true,
'query_builder' => function ($repository)
here is the entity just for reference
class Customer
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Assert\NotBlank(message="Please enter a Customer ID.")
* #Assert\Length(max="32")
* #ORM\Column(type="string", length=32)
* #var string
*/
protected $accountId;
/**
* #Assert\NotBlank(message="Please enter a company name.")
* #Assert\Length(max="60")
* #ORM\Column(type="string", length=60)
* #var string
*/
protected $name;
And one last time... I want to go from this:
To this:
Create a simple getter and use that as the property, eg:
public function getNamePlusAccountId()
{
return $this->name." (".$this->accountId.")";
}
and use 'property' => 'namePlusAccountId' in your form.
If you only need to change the label but would like to keep the form field value then http://symfony.com/doc/current/reference/forms/types/entity.html#choice-label probably what are you looking for
I am trying to make a multiple-select ChoiceType in my Symfony form. However, I am getting the following error:
Unable to transform value for property path "[organisations]":
Expected an array.
Note: If I change the name of the component from organisations to anything else, it's rendering the form correctly.
As far as I can see, organisations is an array:
/**
* #var Organisation[]
* #ORM\ManyToMany(targetEntity="Booking\Entity\Organisation", inversedBy="users")
* #ORM\JoinTable(name="users_organisations")
*/
protected $organisations;
Here's the form:
$organisations = $doctrine->getRepository('Booking\Entity\Organisation')->findAll();
$builder
->add('organisations', ChoiceType::class, array(
'choices' => $organisations,
'choice_label' => function($organisation, $key, $index) {
return $organisation->getName();
},
'multiple' => true
))
What am I doing wrong?
Use EntityType instead.
$builder
->add('organisations', EntityType::class, array(
'choices' => $organisations,
'choice_label' => function($organisation, $key, $index) {
return $organisation->getName();
},
'multiple' => true
))
I posted this just because people (like me) don't usually read all the comments. Merit goes to Jakub.
I'm new to symfony2 and I'm building my first online store with it. I have products and I want to add product sizes, one product can have many sizes and one size can have many products. For example: two products cat have 'M' size.
class Product {
...
/**
* #ORM\ManyToMany(targetEntity="Size", inversedBy="products", cascade={"persist", "merge"})
* #ORM\JoinTable(name="sizes")
*/
private $sizes;
}
//in another file
class Size {
/**
* #ORM\ManyToMany(targetEntity="Product", mappedBy="sizes")
*/
protected $products;
}
ProductController.php
...
->add('sizes', CollectionType::class, [
'entry_type' => SizeType::class,
'label' => 'Sizes',
'allow_add' => true,
])
...
SizeType.php
public function buildForm(FormBuilderInterface $builder, array $options) {
$repo = $this->em->getRepository('AppBundle:Size');
$q = $repo->createQueryBuilder('c')
->getQuery();
$sizes = $q->getResult();
$builder->add('name', EntityType::class, array(
'class' => 'AppBundle:Size',
'choice_label' => 'name',
));
}
Right now I'm getting
Catchable Fatal Error: Object of class AppBundle\Entity\Size could not be converted to string I can fix if I implement __toString() but I don't know if this is the right thing to do, and if I do this, when editing the product, the dropdown doesn't select the right size.
My question is, is this the right way to implement product - sizes function to online store?
Try with this code:
$builder->add('name', EntityType::class, array(
'class' => 'AppBundle:Size',
'choice_label' => 'name',
'property' => 'needed_property_name' //just write the needed property name there
));
So I've figured out better way to do it, 'entity' type with multiple => true
->add('sizes', 'entity', [
'class' => Size::class,
'label' => 'Размери',
'choice_label' => 'name',
'multiple' => true,
'expanded' => false,
//'allow_add' => true,
])
This way multiple sizes can be selected, with bootstrap-multiselect I've made it good looking and perfectly works for me now.
I'd love to hear if there is a better way.
Product annotations looks wrong. The JoinTable is a lookup table for many-to-many relation:
The convention is to name it after linked tables: products_sizes in your case:
class Product {
...
/**
* #ORM\ManyToMany(targetEntity="Size", inversedBy="products", cascade={"persist", "merge"})
* #ORM\JoinTable(name="products_sizes")
*/
private $sizes;
}
I have an entity which DishesWithCategory by the link to other entities:
/**
* #ORM\ManyToOne(targetEntity="Dishes", cascade={"persist"})
*/
protected $dishes;
/**
* #ORM\ManyToOne(targetEntity="MenuCategory", cascade={"persist"})
*/
protected $category;
In admin i have:
$formMapper
->add('dishes', 'sonata_type_admin', [
'delete' => false,
'btn_add' => false
])
->add('category', 'sonata_type_model',[
'expanded' => true,
'multiple' => true,
])
;
When I try to create a dish, I get the error:
Found entity of type Doctrine\Common\Collections\ArrayCollection on association ZaWeb\MenuBundle\Entity\DishesWithCategory#category, but expecting ZaWeb\MenuBundle\Entity\MenuCategory
Can someone faced with this? how can I fix it?
I didn't fully understand your model but i think that the issue comes from : the multiple => true on category because you can set only one category (ManyToOne) for a DishesWithCategory.
Either you need to change your model to a OneToMany for your $category or you need to remove the ArrayCollection which might be in the constructor of your model and remove multiple => true.
You might need to do :
$formMapper
->add('dishes', 'sonata_type_admin', [
'delete' => false,
'btn_add' => false
])
->add('category', 'sonata_type_model',[
'expanded' => true
])
;
I have 3 Entities: Person, Affiliation and PersonAffiliation.
In my form, I will display each affiliation as a checked checkbox.
Nowm when the user uncecks the checkbox and click submit, this affiliation should be removed from the PersonAffiliation table.
The problem is that when I submit without unchecking, my data are duplicated.
Example: aff1 and aff2. When both checked and submit, I will then get aff1 aff1 aff2 aff2.
The same, If I uncheck aff2, I will then have aff1 aff1.
The error is probably somewhere in using the doctrine:
Here is how I am managing that:
Entity Persom
#ORM\OneToMany(targetEntity="PersonAffiliation", mappedBy="person", cascade={"persist", "remove"})
protected $affiliations;
Entity Affiliation:
#ORM\OneToMany(targetEntity="PersonAffiliation", mappedBy="affiliation")
protected $person_affiliations;
Entity PersonAffiliation
#ORM\ManyToOne(targetEntity="Person", inversedBy="affiliations")
#ORM\JoinColumn(name="person_id", referencedColumnName="id")
protected $person;
#ORM\ManyToOne(targetEntity="Affiliation", inversedBy="person_affiliations")
#ORM\JoinColumn(name="affiliation_id", referencedColumnName="id")
protected $affiliation;
An idea on how to resolve that?
Thank you.
EDIT:
Cotroller part:
foreach( $enquiry->getAffiliations() as $aff )
{
$pAff = new PersonAffiliation();
$pAff->setPersonId( $person->getId() );
$pAff->setAffiliationId( $aff->getAffiliation()->getId() );
$pAff->setPerson( $person );
$pAff->setAffiliation( $aff->getAffiliation() );
$em->persist($pAff);
$em->flush();
}
Form Part:
public function buildForm(FormBuilder $builder, array $options)
{
$person = $this->person;
$user = $this->user;
$builder->add('firstname', 'text');
$builder->add('middlename', 'text', array('required'=>false));
$builder->add('lastname', 'text');
$builder->add('sex', 'choice', array( 'choices' => array('m' => 'Male', 'f' => 'Female'),
'required' => true,
'multiple' => false,
'expanded' => true));
$builder->add('email', 'text', array('required'=>false));
if( $this->addAffiliations ) {
$builder->add('affiliations', 'entity', array(
'label' => 'Athor\'s affiliations',
'class' => 'SciForumVersion2Bundle:PersonAffiliation',
'query_builder' => function($em) use ($person, $user){
return $em->createQueryBuilder('pa')
->where('pa.person_id = :pid')
->setParameter('pid', $person->getId());
},
'property' => 'affiliation',
'multiple' => true,
'expanded' => true,
));
}
}
In the Person entity :
/**
* #ORM\ManyToMany(targetEntity="Affiliation", inversedBy="people")
* #ORM\JoinTable(name="PersonAffiliation")
*/
protected $affiliations;
And in the Affiliation entity :
/**
* #ORM\ManyToMany(targetEntity="Person", mappedBy="affiliations")
*/
protected $people;
You made a $em->flush() on each iteration of the foreach. It should be done after the end of foreach isnt'it ?
Moreover, you may use a ManyToMany relation.