I have an entity Log
(table log
) with members resourceType
and resourceId
(with columns resource_log
and resource_id
). The resourceType
can e.g. Order
(for actions on orders, e.g. status changes ) or Whatever
(for Whatever
related actions). There is no relationships (neither in Doctrine, nor in the database) between the Log
and the "resource" entities/tables.
Now I want to select only the Log
s, that are related to Order
s with myOrderProperty = "someValue"
. That means:
SELECT
*
FROM
`log`
JOIN
`order` ON `order`.`id` = `log`.`resource_id` AND `log`.`resource_type` = 'order'
WHERE
`order`.`my_order_property` LIKE '%my_order_property_value%'
But the code
$queryBuilder = $this->entityManager->createQueryBuilder();
$queryBuilder->select('l')->from(Log::class, 'l');
$queryBuilder->join('l.order', 'o');
...
$queryBuilder
->where('o.myOrderProperty = :myOrderProperty')
->setParameter('myOrderProperty', $myOrderProperty);
doesn't work, since the entity Log
doesn't have any relationship with the Order
(though it has a property order
):
[Semantical Error] line 0, col 102 near 'o WHERE o.myOrderProperty': Error: Class MyNamespace\Log has no association named order
How to JOIN
without a relationship defined between two entities?
I know, I could use inheritance. But semantically it's not an inheritance case. So is there another way for solving the problem?
That's not true. As of Doctrine 2.3 or 2.4 (I don't remember anymore but both are already old anyway), arbitrary joins are supported, allowing to perform such joins without defining bidirectional relations.
It uses the Data Mapper pattern at the heart, aiming for a complete separation of your domain/business logic from the persistence in a relational database management system. The benefit of Doctrine for the programmer is the ability to focus on the object-oriented business logic and worry about persistence only as a secondary problem.
Actually, not true! As Stof suggested in the comments on this page, it is possible to query over this join without mapping this side of the relationship, it just takes a little bit more work:
it's required if you're doing a JOIN in this direction. That's not true. As of Doctrine 2.3 or 2.4 (I don't remember anymore but both are already old anyway), arbitrary joins are supported, allowing to perform such joins without defining bidirectional relations.
The JOIN
without relationship can be implemented like this:
$queryBuilder = $this->entityManager->createQueryBuilder();
$queryBuilder->select('l')->from(Log::class, 'l');
$queryBuilder->join(
Order::class,
'o',
\Doctrine\ORM\Query\Expr\Join::WITH,
'o.id = l.resourceId'
);
...
$queryBuilder
->where('o.myOrderProperty = :myOrderProperty')
->setParameter('myOrderProperty', $myOrderProperty);
The only problem is, that the joined entities are not added to the main entity, so that $myLog->getOrder(...)
returns null
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With