Symfony2 entity field in a form - php

I'm trying to create a simple form to add companies and i've a trouble using an entity.
I added a select field using a company type entity :
->add('idtypesociete', 'entity', array('class' => 'PromocastUtilisateurBundle:PcastTypesociete', 'property' => 'nomtypesociete'))
But when i submit the form my idtypesociete field contain an 'PcastTypesociete' object and not just the value of the option selected. So the submission fail.
I made a Many-To-One relation between my company entity and my typeCompany entity like this:
/**
* #var integer $idtypesociete
*
* #ORM\Column(name="IDTYPESOCIETE", type="integer", nullable=false)
* #ORM\ManyToOne(targetEntity="Promocast\UtilisateurBundle\Entity\PcastTypesociete")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="PcastTypesociete_idtypesociete", referencedColumnName="idtypesociete")
* })
*/
private $idtypesociete;
Do you have a solution to get only the id of the company type selected? (if possible without made a simple sql request to list my companies types)
Thanks a lot !

If the relationships are working then Symfony 2 usually does a very good job of building the form fields for you.
I think the issue is the $idtypesociete property. Are you expecting to store an integer here on the hydrated entity?
Doctrine associations use Entity relationships. The annotations you supply determine the behind-the-scenes stuff like the join column:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#many-to-one-unidirectional
I suggest backing up or committing your work before doing anything else.
Does changing the entity property to the following help?
/**
* #var PcastTypesociete $typesociete
*
* #ORM\Column(name="IDTYPESOCIETE", type="integer", nullable=false)
* #ORM\ManyToOne(targetEntity="Promocast\UtilisateurBundle\Entity\PcastTypesociete")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="PcastTypesociete_idtypesociete", referencedColumnName="idtypesociete")
* })
*/
private $typesociete;
You may need to update your database schema via doctrine:schema:update using the console if it doesn't work properly the first time. Your Entity will also need to be updated to reflect the new property name.
If that works then your form should only need ->add('typesociete') in the form type and you'll have a functioning entity select field because Symfony is clever enough to know what field type to use.

Related

Doctrine prevent object deletion

In my project I have two entities: planifications and selections.
There is a relation between these two objects: A planification MUST contain ONE selection. The same selection can be used by multiple planifications.
The generated code looks like this:
// Planification.php - class Planification
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Selection", inversedBy="planifications")
* #ORM\JoinColumn(name="selection_id", referencedColumnName="id")
*/
private $selection;
// Selection.php - class Selection
/**
* #ORM\OneToMany(targetEntity="App\Entity\Planification", mappedBy="selection")
*/
private $planifications;
What I would like to do is not allow a selection to be deleted if it is referenced by a planification. In other words, if a planification contains a selection - that selection can not be deleted. What happens to me is if I try to delete a selection that is in a planification, the operation completes successfully, and the $selection member in the Planification class contains NULL.
Would fixing this be possible in doctrine? I have tried adding nullable=false (on the $selection member) and onDelete="NO ACTION", and both solutions don't work.
The correct Doctrine annotation to disallow Planification::$selection to be null, would be:
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Selection", inversedBy="planifications")
* #ORM\JoinColumn(name="selection_id", nullable=false)
*/
private $selection;
(You do not need the referencedColumnName setting, since it defaults to id, and nullable=false goes in the #JoinColumn annotation).
Having the annotation will not update the DB to fit this particular definition.
Execute bin/console doctrine:schema:update --dump-sql to see the needed SQL to update your table definition, and run the resultant appropriate SQL statements against your DB to update the DB schema.

Symfony3.4 - collection reference same entity field lose linked association

Sorry about the title, it's quite hard to describe it with just a few words. Here's the problem:
I have a customer entity which has a OneToMany with Website and customerTrackingIds :
class Customer {
...
/**
* #var ArrayCollection
* #Serializer\Exclude()
* #ORM\OneToMany(targetEntity="AppBundle\Entity\WebSite", mappedBy="customer",cascade={"persist","remove"},orphanRemoval=true)
*/
private $webSites;
/**
* #var ArrayCollection
* #Serializer\Exclude()
* #ORM\OneToMany(targetEntity="AppBundle\Entity\CustomerTrackingId", mappedBy="customer",cascade={"persist","remove"})
*/
private $customerTrackingIds;
...
}
And Website:
class WebSite {
/**
* #var Customer
* #Serializer\MaxDepth(1)
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Customer", inversedBy="webSites")
* #ORM\JoinColumn(nullable=true, onDelete="SET NULL")
*/
private $customer;
/**
* #var ArrayCollection
* #Serializer\Exclude()
* #ORM\OneToMany(targetEntity="AppBundle\Entity\CustomerTrackingId", mappedBy="website")
*/
private $customerTrackingIds;
}
Customer has multiple website and multiple trackingIds. Each tracking ID is associated with one of the customer's website, but more trackingIds can exist for the same Website.
I use https://github.com/ninsuo/symfony-collection to handle the collection of website/trackingIds in the same page but when i go edit the information something really weird (at least for me) happens.
Looking in my debugger session i saw that when the form loads data from submit in my controller:
$formCustomer = $this->createForm( CustomerFormType::class, $customer );
$formCustomer->handleRequest( $request );
if ( $formCustomer->isSubmitted() && $formCustomer->isValid() ) {
$em = $this->getDoctrine()->getManager();
$em->persist( $customer );
$em->flush();
When the request is handled all of the elements of TrackingIds has their website correctly set, but inside the website the customer link gets lost (becomes null).
What happens next is that when all the data get persisted i lost in my database the phisical association between website <-> customer (customer becomes null)
How can i fix this?
If you will ever land here i solved the issue simply double-checking my website collection form type.
Since using https://github.com/ninsuo/symfony-collection i created a new FormTheme to render the collection add/delete stuff in my page with just one field for the website collection which was the website name.
Anyways, inside my website collection formType i had TWO fields, name AND, guess what, CUSTOMER.
Since the FormTheme was rendering just the name field, the other one becomes null automatically, so when it was handled by the controller he was actually doing that right.

Doctrine merging entity with unidirectional OneToMany not clearing database entries

First off, I use Doctrine v2.6.2 with Symfony v4.1.7.
I have an entity Product which (among others) has a unidirectional one-to-many relation with another entity AlternativeDuration. Following Doctrine's documentation, the mapping in my product class looks like this:
/**
* #ORM\ManyToMany(
* targetEntity="AlternativeDuration",
* cascade={"persist", "merge", "remove"},
* orphanRemoval=true
* )
* #ORM\JoinTable(name="ProductAlternativeDurations",
* joinColumns={#ORM\JoinColumn(name="product_id", referencedColumnName="id", onDelete="CASCADE", nullable=false)},
* inverseJoinColumns={#ORM\JoinColumn(name="alternative_duration_id", referencedColumnName="id", unique=true, onDelete="CASCADE", nullable=false)}
* )
*/
protected $alternativeDurations;
My application recently started using React, this means I now submit a JSON representation of my product (along with an array of alternative durations) which I need to deserialize into the Product entity in the back-end. I use the JMS serializer with default configuration for this.
Now the problem I'm having happens when editing an existing product, the product already has an alternative duration which I delete. The submitted JSON looks like this:
{
"id": 1, # the ID of the existing product here
"alternativeDurations": [] # empty array because the entry is removed
}
In the back-end I successfully deserialize the JSON string:
$serializedProduct = $this->serializer->deserialize($jsonString, Product::class, 'json');
I verified here that the $serializedProduct has no alternative durations. Then I follow with a merge + flush. I expect the merge to fetch the existing product and supplement it with the $serializedProduct.
$em->merge($serializedProduct); # $em being the EntityManager.
$em->flush();
Now I would expect the AlternativeDuration entry, along with the ProductAlternativeDurations join table entry being removed. The result, however, is that the entry in ProductAlternativeDurations is removed but the AlternativeDuration is still there.
I'm at a loss now, anyone can give some pointers on why the AlternativeDuration entry is not deleted?
EDIT 19-11-2018:
It seems this is a known bug in Doctrine: #2542
Also merge will be removed in Doctrine3 so I will probably need to rethink this approach in general.

Symfony 4 : Doctrine migrate with manyToOne join

I trying Symfony 4 for "fun". And for that I try to rewrite an old website without framework as the moment, with Symfony 4.
For that I configure my app on my database with existing datas. And I'd make login form.
BUT on my User classe, I have some colomn who make me some issues.
See bellow my user's class's annotations:
/**
* Utilisateur
*
* #ORM\Table(name="utilisateur", uniqueConstraints={#ORM\UniqueConstraint(name="mail", columns={"mail"})}, indexes={#ORM\Index(name="FK_UTILISATEUR_idDroit", columns={"idDroit"})})
* #ORM\Entity
*/
and my user's struct :
idutilisateur
nom
prenom
mail
password
dateinscription
datevalidation
token
iddroit
plainPassword
Like you can see, I create before iddroit as foreign key of droit's table.
Doctrine generated the propertie as
/**
* #var Droit
*
* #ORM\ManyToOne(targetEntity="Droit")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="idDroit", referencedColumnName="idDroit")
* })
*/
private $iddroit;
And created the getter as
public function getIddroit(): Droit
{
return $this->iddroit;
}
And after followed the documentation about registration / login, the debugger respond =>
Return value of App\Entity\Utilisateur::getIddroit() must be an
instance of App\Entity\Droit, null returned
So I imagine he want an object and not just an ID, even if in anotation it's making the Join rules. Any ID what's happened ?
And I understand to return an objet, but I have no idea how to return that.
If any suggestion.
Thanks guys ;)
Laurent

ManyToOne relationship + How to use in both directions

I have 2 tables like this:
Users
- UserID
- Username
- Password
- ...
Players
- playerID
- playerName
- ...
- User
The relation is ManyToOne (see the picture) and it's not required.
I've generated my entities automatically with Doctrine. In my player Entity I have:
/**
* #var \NV\VolleyScoutBundle\Entity\Users
*
* #ORM\ManyToOne(targetEntity="NV\VolleyScoutBundle\Entity\Users")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="user_id", referencedColumnName="user_id")
* })
*/
protected $user;
But I don't have a $player variable in my Users Entity. In what way can I add this? Tried to do this but gave me different errors. What I'm trying to do is add a player form to my register form.
So in my RegisterType (=form) I woud like to add ->add('player', new PlayerType()). But that's not possible without a $player variable in my Users entity.
What type of relation do I need to setting for $player in my Users entity?
You have to add annotation in user entity.
In Player Enity
#ORM\OneToMany(targetEntity="Players", mappedBy="user")
protected $player;
In User Entity:
#ORM\ManyToOne(targetEntity="Users", inversedBy="player")
#ORM\JoinColumn(name="user_id", referendecColumn="UserId")
proteced $user;
This is only a draft. You have to write full namespaces for target entities, and correct errors if there are some.
A lot of setails you can find here: Doctrine documentation - working with association
Try to use small caps for table names, because MySQL under linux doesn't like uppercaps.
$player must be instance of ArrayCollection

Categories