Doctrine DQL Delete from relation table - symfony

Using Doctrine 2 and Symfony 2.0.
I have two Doctrine entities (let's suppose EntityA and EntityB).
I have a ManyToMany relation between them. So a EntityA_EntityB table has been created in database.
Using DQL or QueryBuilder, how can I delete from that relation table EntityA_EntityB?
Docrtine offers something like this to perform something similar:
->delete()
->from('EntityA a')
->where('a.id', '?', $id);
But I don't really get how to perform the deletion of row from the relation table.

$em = ...; // instance of `EntityManager`
// fetch both objects if ID is known
$a = $em->getRepository("YourProjectNamespace:EntityA")->find($id_of_A);
$b = $em->getRepository("YourProjectNamespace:EntityB")->find($id_of_B);
// suppose you have `EntityA::getObjectsOfTypeB` which retrieves all of linked objects of type `EntityB`.
// This method return instacne of ArrayCollection
$a->getObjectsOfTypeB()->removeElement($b);
$em->flush();
Something like this?
Basically, you need to remove related object from collection rather than delete relation itself. you want to remove relation directly you can always use pure SQL, but in DQL that is not possible.
Raw DELETE SQL statement via DBAL Connection object
$conn = $this->getDoctrine()->getManager()->getConnection();
$stmt = $conn->prepare("DELETE FROM EntityAEntityB WHERE id_b IN (:ids_of_b)");
$stmt->bindParam('ids_of_b', $to_delete_ids); // BEWARE: this array has to have at least one element
$stmt->executeUpdate();

Related

CreateQueryBuilder on an association table that has no entity

I have an association table, that has no entity itself, inside an entity. I can do a raw or native query on it but I want to use createQueryBuilder on it. How can I?
Here is the raw query that I want to convert to createQueryBuilder:
$sql = 'SELECT t.* FROM tasks t LEFT JOIN question_tasks qt ON t.id = qt.task_id WHERE qt.question_id = :qtId';
$rsm = new ResultSetMappingBuilder($this->_em);
$rsm->addRootEntityFromClassMetadata(Task::class, 't');
$query = $this->_em->createNativeQuery($sql, $rsm);
$query->setParameter('qtId', $questionId);
return $query->getResult();
Thank you.
It's kind of impossible use Doctrine ORM without entity. QueryBuilder just converts down to DQL. DQL make queries over your object model.
Says documentation
You need to think about DQL as a query language for your object model,
not for your relational schema.
Check docs here Doctrine Query Language

Symfony/Doctrine2 and Associative entity

Usually when querying in a custom repository class, I use something like this :
SELECT * FROM BundleName:Entity
But how do I do for associative entity ?
I have an entity "Ticket" and an entity "Tag".
It's a ManyToMany relation.
In phpMyAdmin, I've got a ticket_tag associative table but how do I get it with Doctrine ?
Thank you
You should use createQueryBuilder to handle your custom query requirement, in case if you are having a valid relationship over entities. for example:
Inside ticket repository you should handle like this, if you want to do more operations then you should learn more from here: https://symfony.com/doc/3.3/doctrine/repository.html
$query = $this->createQueryBuilder('t')
->select('count(t.id) as total_ticket, tag.id as tagId')
->leftJoin('t.tags', 'tag')
->groupBy('tag.id')
;
return $query->getQuery()->getResult();

Doctrine2 - proxy object among regular objects in getResult

In my Symfony2 controller, I have two queries:
like in this example:
$object = $this->getDoctrine()->getManager()
->createQuery('SELECT PARTIAL o.{id,name,field1}
FROM SomeBundle:SomeEntity o
WHERE o.id = :objectId')
->setParameter('objectId', $objectId)
->getResult();
$objects = $this->getDoctrine()->getManager()
->createQuery('SELECT PARTIAL o.{id,name,field1, field2}
FROM SomeBundle:SomeEntity o ')
->getResult();
Effect that I receive in collection $objects is collection of SomeBundle:SomeEntity objects except for the one that I received to variable $object for which I receive Proxy object.
If I output $objects collection and for each element I want to print output that includes fields: name, field1, field2, I receive null for field2 for this object. In fact if I get this $object in any other controller launched with this one together, the field2 is also null on each reference to the object.
For example, if I want to display each object as:
name field1 field2
I get following array for $objects:
nameExample field1Example field2Example
nameExample field1Example field2Example
nameExample field1Example
nameExample field1Example field2Example
nameExample field1Example field2Example
where the third row is the $object.
If I get field2 in the first query it is also visible on getResult of the second one. But that makes me control all fields received for any Entity object in whole Request.
What could I made wrong?
How can I avoid that effect? I still want to work with objects not with multidimensional arrays (as for HYDRATE_ARRAY)
Is there a way to force doctrine to result always with entity objects not with proxies objects?
Thank you in advance.
This happens because Doctrine keeps an internal reference to each entity it returns. When you request an entity you've requested before, it will re-use the previous object. The reason for this is that having two different copies of the same entity would create conflicts if you try to manipulate both of them. For more details, see http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork.html#how-doctrine-keeps-track-of-objects
The one solution is to detach the entity you got first (using either $em->detach($object) or $em->clear()) before executing the second query. Be aware, any changes you've made that have not been flushed yet will be gone.
Another option is to either refresh the entity using $em->refresh($object) (this will cause it to be fully loaded) or tell Doctrine it needs to refresh all entities for the second query:
$query = $this->getDoctrine()->getManager()->createQuery('SELECT PARTIAL o.{id,name,field1, field2} FROM SomeBundle:SomeEntity o ');
$query->setHint(Query::HINT_REFRESH, true);
$objects = $query->getResult();
This will make Doctrine refresh all the entities it finds for this second query.

Doctrine duplicating query results?

I have the following code
$this->em = $this->container->get('doctrine.orm.entity_manager');
$qb = $this->em->getRepository('CoreBundle:ServiceProvider')->createQueryBuilder('c');
$qb->select('count(venue.id) as vencount');
$qb->from('CoreBundle:ServiceProvider','venue');
$count = $qb->getQuery()->getOneOrNullResult()['vencount'];
which is write its returning a number of venues but the problem is that this number is mistaken because in the ServiceProvider table i have only 5 records but this query is returning 25. I tried to add a new record so they are 6 and yes the result was 36.
So I added group by the id and it fixed the issue anyone can tell me why is this happening ?
It's because when you create a query from a repository Doctrine assumes its a select and inject the select and from clausule's for you.
This is the sql you get from using the getRepository method:
SELECT count(i0_.id) AS sclr_0 FROM Entity i1_, Entity i0_
(Note that the entity is twice in the FROM).
Using just:
$qb = $this->em->createQueryBuilder();
$qb->select('count(venue.id) as vencount');
$qb->from('CoreBundle:ServiceProvider','venue');
You get:
SELECT count(i0_.id) AS sclr_0 FROM Entity i0_
Which is probably what you are looking for.
Another alternative is to get it from the repository but clear the sql parts with:
$qb = $this->em->getRepository('CoreBundle:ServiceProvider')->createQueryBuilder('c')->resetDQLParts();
But this way you lost the very purpose of using the repository in the first place.

Automatically add a Join statement in findBy magic method

I'm using Symfony2 / Doctrine2.
I'm trying to override the BaseEntityRepository Class so the magic findBy method automatically adds a JOIN on a "translations" relation. It was easy to do in Symfony 1.4/Doctrine 1, because it was manipulating a Doctrine_Query object, so I simply had to $query->addJoin() and it did the trick.
Unfortunately, in Doctrine 2 you only receive an array of criteria as parameter, and that's where I'm stucked.
I got many entities which have a one-to-many relationship with a translation entity.
For exemple : Section as a one-to-many relationship with SectionTranslation
The goal is to retrieve only the "active" sections (active is in SectionTranslation) when using SectionRepository->findAll(); (or even findBy).
The wanted DQL result is : Select * from Section INNER JOIN SectionTranslation ON Section.id = SectionTranslation.translatable_id WHERE SectionTranslation.locale = $locale AND SectionTranslation.active = 1;
Any idea?
The solution could be adding event listener for particular entity and particular method.

Resources