Doctrine Single Table Inheritance: Join on Parent Association from child Entity not working. FOSUserBundle - database

I have classes
IdentityUser (the user account, which extends the FOSUserBundle)
Person ( person or user of the system which have userAccount (IdentityUser)
Marketer ( a marketer user )
EDIT ( added use statements on classes )
The user account inheritated from FOSUSerBundle
namespace Elite\Security\Identity;
use FOS\UserBundle\Model\User as FOSUser;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="users")
*/
class IdentityUser extends FOSUser
{
/**
* #var integer The id
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
}
namespace Elite\Common\Entity;
use FOS\UserBundle\Model\UserInterface;
use Elite\Common\ValueObject\PersonName;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\Table(name="people")
*/
class Person
{
/**
* #var integer The id
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
*
* #var \Elite\Common\ValueObject\PersonName The name of the person
*
* #ORM\Embedded(class="Elite\Common\ValueObject\PersonName", columnPrefix=false)
*/
protected $name;
/**
* #var \ The user identity of the person
*
* #ORM\ManyToOne(targetEntity="Elite\Security\Identity\IdentityUser")
* #ORM\JoinColumn(name="user_account_id", referencedColumnName="id")
*/
protected $userAccount;
public function __construct(UserInterface $account, PersonName $name)
{
$this->userAccount = $account;
$this->name = $name;
}
}
use Elite\Common\Entity\Person;
use Elite\Infrastructure\Doctrine\Adapter\Collection;
use FOS\UserBundle\Model\UserInterface;
use Doctrine\ORM\Mapping as ORM;
use Elite\Common\ValueObject\PersonName;
/**
* Class Marketer
* #package Elite\Emti\Marketing
*
* #ORM\Entity
*/
class Marketer extends Person
{
public function __construct(UserInterface $userAccount, PersonName $name)
{
parent::__construct($userAccount, $name);
$this->assignments = new Collection();
}
}
now what im trying to do is
query a Marketer
where the userAccount's username
is dana
EDIT
here is my query
$doctrine = $this->container->get('doctrine');
$em = $doctrine->getManager('inquiry');
$qb = $doctrine->getRepository('EmtiInquiry:Marketer', 'inquiry')->createQueryBuilder('m');
$dana = $qb->join('m.userAccount', 'account')
->where('account.username = :username')
->setParameter('username', 'dana')
->getQuery()
->getSingleResult();
but I dont get results or error like
[Doctrine\ORM\Query\QueryException]
[Semantical Error] line 0, col 91 near 'username = :': Error: Class Elite\S
ecurity\Identity\IdentityUser has no field or association named username
[Doctrine\ORM\Query\QueryException]
SELECT u FROM Elite\Emti\Inquiry\Marketer u INNER JOIN u.userAccount accoun
t WHERE account.username = :username

Related

Symfony 4 formbuilder loop each rows from database table

I have 2 entities :
Recettes
Categories
I try to build/list a form based on each rows of the table "Recettes" and display it from a controller.
Any ideas?
=======================
FORM_START
Name1 (TypeText) | Category (ChoiceType)
Name2 (TypeText) | Category (ChoiceType)
Name3 (TypeText) | Category (ChoiceType)
[Submit button]
FORM_END
=======================
Entity RECETTES
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Recettes
*
* #ORM\Table(name="recettes", indexes={#ORM\Index(name="categorie", columns={"categorie"})})
* #ORM\Entity
*/
class Recettes
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=50, nullable=false)
*/
private $nom;
/**
* #var \Categories
*
* #ORM\ManyToOne(targetEntity="Categories")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="categorie", referencedColumnName="id")
* })
*/
private $categorie;
public function getId(): ?int
{
return $this->id;
}
public function getNom(): ?string
{
return $this->nom;
}
public function setNom(string $nom): self
{
$this->nom = $nom;
return $this;
}
public function getCategorie(): ?Categories
{
return $this->categorie;
}
public function setCategorie(?Categories $categorie): self
{
$this->categorie = $categorie;
return $this;
}
}
Entity CATEGORIES
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Categories
*
* #ORM\Table(name="categories")
* #ORM\Entity
*/
class Categories
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=50, nullable=false)
*/
private $nom;
public function getId(): ?int
{
return $this->id;
}
public function getNom(): ?string
{
return $this->nom;
}
public function setNom(string $nom): self
{
$this->nom = $nom;
return $this;
}
}
In symfony/forms each Form is an EventDispatcherInterface.
You can subscribe to one of the Events your form fires 🔥
In your case you want to add fields before your form is beeing processed.
class FriendMessageFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$builder->add('activate_recette_1', ChoiceType::class);
$builder->add('activate_recette_2', ChoiceType::class);
});
}
}
You can inject your RecetteRepository via Dependency-Injection ans use the results.
Listen to the form events via:
Event-Listener
Event-Subscriber

Defining extended entities in sonata

I have some base entity that defines some fields which all (or at least most of) other entities should have. It looks like:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity()
* #ORM\MappedSuperclass
* #ORM\HasLifecycleCallbacks()
*/
abstract class BaseEntity {
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="boolean")
*/
protected $published;
/**
* #ORM\Column(type="datetime")
*/
protected $createdAt;
/**
* #ORM\Column(type="datetime")
*/
protected $updatedAt;
public function getId(): ?int
{
return $this->id;
}
and so on...getters and setters.
Then I have entity i.e. ArticleCategory extending that BaseEntity:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\ArticleCategoryRepository")
*/
class ArticleCategory extends BaseEntity
{
/**
* #ORM\Column(type="string", length=255)
*/
private $title;
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
}
So, it's just adding one extra field - title.
Then, I have base admin class:
namespace App\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use App\Entity\BaseEntity;
class BaseAdmin extends AbstractAdmin
{
/**
* #param BaseEntity $entity
*/
public function prePersist($entity)
{
$now = new \DateTime();
$entity->setCreatedAt($now);
$entity->setUpdatedAt($now);
$entity->setPublished(true);
}
}
And then admin class for that ArticleCategory entity:
namespace App\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\Form\Extension\Core\Type\TextType;
final class ArticleCategoryAdmin extends BaseAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('title', TextType::class);
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('title');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('title');
}
}
Problem is when I go to sonata list page instead of displaying all entities in ArticleCategory type I get an sql error:
Unknown column 'b0_.id' in 'field list'
And query looks like this:
SELECT b0_.id AS id_0, b0_.published AS published_1, b0_.created_at AS created_at_2, b0_.updated_at AS updated_at_3, a1_.title AS title_4
FROM article_category a1_
WHERE a1_.id IN (?, ?)
ORDER BY a1_.id ASC' with params [2, 3]
So sonata is getting data from correct table (article_category) and making an alias for it "a1_" and all fields that are directly inside ArticleCategory (title) are collected well, with that alias.
But all other fields that belong to base class (BaseEntity) sonata is trying to get via some un-existing alias "b0_" and query fails of course.
Any idea how to solve this? How to tell sonata that all the fields belong to the same table even they belong to 2 entity classes?
Found the problem. At the beginning where base entity was defined I had:
/**
* #ORM\Entity()
* #ORM\MappedSuperclass
* #ORM\HasLifecycleCallbacks()
*/
Which is not correct because of that "Entity()" row. That had to be removed. It can't be entity and mapped supper class at the same time.
/**
* #ORM\MappedSuperclass
* #ORM\HasLifecycleCallbacks()
*/

Symfony 3 Database Join

I need a result with all the entries of two tables.
With this SQL Statement I get my wished result, but how can I archieve this in symfony?
In my result i want to connect dataset.id with datasetFile.dataset_id
how can i get it with maybe join in symfony 3.
Select *
from dataset
LEFT JOIN dataset_file ON dataset.id=dataset_file.dataset_id
class Dataset
...
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="strap_id", type="integer")
* #Assert\NotBlank()
*/
protected $strap_id;
/**
* #ORM\Column(name="user_id", type="integer")
*/
protected $user_id;
/**
* #ORM\Column(name="start_date", type="date")
* #Assert\Date()
*/
protected $start_date;
/**
* #ORM\Column(name="end_date", type="date", nullable=true)
* #Assert\Date()
*/
protected $end_date;
/**
* #ORM\Column(name="status", type="integer")
*/
protected $status;
...
DatasetFile
...
/**
* #ORM\ManyToOne(targetEntity="Dataset")
* #ORM\JoinColumn(name="dataset_id", referencedColumnName="id")
*/
private $dataset;
...
This is an inverse relationship as I understand. Try to add inversedBy in the $dataset annotation.
/**
* #ORM\ManyToOne(targetEntity="Dataset", inversedBy="id")
* #ORM\JoinColumn(name="dataset_id", referencedColumnName="id")
*/
private $dataset;
The $dataset property is an instance of Dataset. The DatasetFile entity should have setter and getter for $dataset like following.
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Dataset", inversedBy="id")
* #ORM\JoinColumn(name="dataset_id", referencedColumnName="id")
*/
private $dataset;
/**
* DatasetFile constructor.
*/
public function __construct()
{
}
/**
* #return int
*/
public function getId(): int
{
return $this->id;
}
/**
* #param int $id
*
* #return DatasetFile
*/
public function setId(int $id): DatasetFile
{
$this->id = $id;
return $this;
}
/**
* #return Dataset
*/
public function getDataset(): Dataset
{
return $this->dataset;
}
/**
* #param Dataset $dataset
*
* #return DatasetFile
*/
public function setDataset(Dataset $dataset): DatasetFile
{
$this->dataset = $dataset;
return $this;
}
Use this property like
/**
* #param DatasetFile $datasetFile
*
*/
public function doSomthing (DatasetFile $datasetFile): void
{
/** #var Dataset $dataset */
$dataset = $datasetFile->dataset;
....
....
}

Foreign key not stored in database using embed form in symfony 3

I have the following entities, form types and controller
Entity Client
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Client
*
* #ORM\Table(name="client")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ClientRepository")
*/
class Client
{
/**
* #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="address", type="string", length=255)
*/
private $address;
/**
* #ORM\OneToMany(targetEntity="Contacts", mappedBy="client", cascade={"persist"})
*/
private $contacts;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Client
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set address
*
* #param string $address
*
* #return Client
*/
public function setAddress($address)
{
$this->address = $address;
return $this;
}
/**
* Get address
*
* #return string
*/
public function getAddress()
{
return $this->address;
}
/**
* Constructor
*/
public function __construct()
{
$this->contacts = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add contact
*
* #param \AppBundle\Entity\Contacts $contact
*
* #return Client
*/
public function addContact(\AppBundle\Entity\Contacts $contact)
{
$this->contacts[] = $contact;
return $this;
}
/**
* Remove contact
*
* #param \AppBundle\Entity\Contacts $contact
*/
public function removeContact(\AppBundle\Entity\Contacts $contact)
{
$this->contacts->removeElement($contact);
}
/**
* Get contacts
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getContacts()
{
return $this->contacts;
}
}
Contacts entity is as below
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Contacts
*
* #ORM\Table(name="contacts")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ContactsRepository")
*/
class Contacts
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="fullname", type="string", length=255)
*/
private $fullname;
/**
* #var int
*
* #ORM\Column(name="user_type", type="smallint")
*/
private $userType;
/**
* #ORM\ManyToOne(targetEntity="Client", inversedBy="contacts")
* #ORM\JoinColumn(name="client_id", referencedColumnName="id")
*/
private $client;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set fullname
*
* #param string $fullname
*
* #return Contacts
*/
public function setFullname($fullname)
{
$this->fullname = $fullname;
return $this;
}
/**
* Get fullname
*
* #return string
*/
public function getFullname()
{
return $this->fullname;
}
/**
* Set userType
*
* #param integer $userType
*
* #return Contacts
*/
public function setUserType($userType)
{
$this->userType = $userType;
return $this;
}
/**
* Get userType
*
* #return int
*/
public function getUserType()
{
return $this->userType;
}
/**
* Set client
*
* #param \AppBundle\Entity\Client $client
*
* #return Contacts
*/
public function setClient(\AppBundle\Entity\Client $client = null)
{
$this->client = $client;
return $this;
}
/**
* Get client
*
* #return \AppBundle\Entity\Client
*/
public function getClient()
{
return $this->client;
}
}
Client form type is as below
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use AppBundle\Entity\Client;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
class ClientForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class, array('attr' => array('class' => 'form-control', 'placeholder' => 'Client Name')))
->add('address', TextType::class, array('attr' => array('class' => 'form-control', 'placeholder' => 'Address')))
->add('contacts', CollectionType::class, array(
// each entry in the array will be an "email" field
'entry_type' => ContactsForm::class,
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
))
->add('save', SubmitType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Client::class,
));
}
}
Contacts form type is as below
<?php
namespace AppBundle\Form;
use AppBundle\Entity\Contacts;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class ContactsForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('fullname', TextType::class, array('attr' => array('class' => 'form-control', 'placeholder' => 'Full Name')))
->add('user_type', TextType::class, array('attr' => array('class' => 'form-control', 'placeholder' => 'Co-Owner'))
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Contacts::class,
));
}
}
Finally the controller to store data in two different tables being client as main table and contacts having foreign ken as client_id from table client is as below
/
**
* #Route("/client/add", name="add_client")
*/
public function addClientAction(Request $request)
{
$client = new Client();
$form = $this->createForm(ClientForm::class, $client);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$client = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($client);
$em->flush();
$this->addFlash(
'notice',
'Client Added!'
);
return $this->redirectToRoute('homepage');
}
return $this->render('default/addClient.html.twig', array('form' => $form->createView()));
}
The problem here is the data is added in both tables but the foreign key of the added client is not stored in table contacts, the value is null
This solution seems to work for some people may be for older version of symfony
But not luck to me. How to insert the foreign id as well. Am new to symfony and I am using symfony 3.2
It seems for me like a little mess up.
I guess you should add a contact from ContactController addAction.
Than in your Contact form type add EntityType, so you can choose a client for your contact. Here is some examples: http://symfony.com/doc/current/reference/forms/types/entity.html
Or you can set client manually by simple $contact->setClient($client) before you presist.
PS: rename Contacts entity to Contact. It is a little confusing)

Symfony2 Association class form

This is my first Symfony project, and I can't figure out how to solve my problem.
Basically, i'm trying to make an invoice using a form.
I have a "Facturation" (ie invoice) Entity, a "TypeOfService" Entity, and a "Service" Entity (the sole attribute of which is the quantity of the type of service needed for the invoice) that acts as an association class.
I'd like to dynamically add "New Service" fields to my FacturationType form using Javascript (probably AngularJS). So I have to create N new Service entities that each associate with both my Facturation entity and an existing TypeOfService entity.
Here's my Facturation entity:
use Doctrine\ORM\Mapping AS ORM;
/**
* Facturation
*
* #ORM\Table(name="facturation")
* #ORM\Entity
*/
class Facturation
{
...
/**
* #ORM\OneToMany(targetEntity="Service", mappedBy="facturation")
*/
private $service;
/**
* Add service
*
* #param \AppBundle\Entity\Service $service
* #return Facturation
*/
public function addService(\AppBundle\Entity\Service $service)
{
$this->service[] = $service;
return $this;
}
/**
* Remove service
*
* #param \AppBundle\Entity\Service $service
*/
public function removeService(\AppBundle\Entity\Service $service)
{
$this->service->removeElement($service);
}
/**
* Get service
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getService()
{
return $this->service;
}
}
Then Service:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping AS ORM;
/**
* Service
*
* #ORM\Table(name="service")
* #ORM\Entity
*/
class Service
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="integer", nullable=true)
*/
private $quantity;
/**
* #ORM\ManyToOne(targetEntity="TypeOfService", inversedBy="service")
* #ORM\JoinColumn(name="type_of_service_id", referencedColumnName="id")
*/
private $typeOfService;
/**
* #ORM\ManyToOne(targetEntity="Facturation", inversedBy="service")
* #ORM\JoinColumn(name="facturation_id", referencedColumnName="id")
*/
private $facturation;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set quantity
*
* #param integer $quantity
* #return Service
*/
public function setQuantity($quantity)
{
$this->quantity = $quantity;
return $this;
}
/**
* Get quantity
*
* #return integer
*/
public function getQuantity()
{
return $this->quantity;
}
/**
* Set typeOfService
*
* #param \AppBundle\Entity\TypeOfService $typeOfService
* #return Service
*/
public function setTypeOfService(\AppBundle\Entity\TypeOfService $typeOfService = null)
{
$this->typeOfService = $typeOfService;
return $this;
}
/**
* Get typeOfService
*
* #return \AppBundle\Entity\TypeOfService
*/
public function getTypeOfService()
{
return $this->typeOfService;
}
/**
* Set facturation
*
* #param \AppBundle\Entity\Facturation $facturation
* #return Service
*/
public function setFacturation(\AppBundle\Entity\Facturation $facturation = null)
{
$this->facturation = $facturation;
return $this;
}
/**
* Get facturation
*
* #return \AppBundle\Entity\Facturation
*/
public function getFacturation()
{
return $this->facturation;
}
}
And finally TypeOfService
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping AS ORM;
/**
* TypeOfService
*
* #ORM\Table(name="type_of_service")
* #ORM\Entity
*/
class TypeOfService
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(nullable=true)
*/
private $name;
/**
* #ORM\Column(type="integer", nullable=true)
*/
private $pricePerUnit;
/**
* #ORM\OneToMany(targetEntity="Service", mappedBy="typeOfService")
*/
private $service;
...
/**
* Constructor
*/
public function __construct()
{
$this->service = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add service
*
* #param \AppBundle\Entity\Service $service
* #return TypeOfService
*/
public function addService(\AppBundle\Entity\Service $service)
{
$this->service[] = $service;
return $this;
}
/**
* Remove service
*
* #param \AppBundle\Entity\Service $service
*/
public function removeService(\AppBundle\Entity\Service $service)
{
$this->service->removeElement($service);
}
/**
* Get service
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getService()
{
return $this->service;
}
}
Can anyone point me in the right direction ?
For anyone looking, I've cracked it.
This was what I was looking for:
http://symfony.com/doc/current/cookbook/form/form_collections.html
This allows for dynamic field additions, using JS.
Be careful to cascade your association. In my case:
class Facturation
{
....
/**
* #ORM\OneToMany(targetEntity="Service", mappedBy="facturation", cascade={"persist", "remove"})
*/
private $services;

Resources