Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to JOIN without a relationship in Doctrine?

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 Logs, that are related to Orders 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?

like image 703
automatix Avatar asked Aug 26 '17 23:08

automatix


People also ask

Is it possible to do an arbitrary join in doctrine?

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.

What is doctrine and how does it work?

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.

Is it possible to query over a join without mapping it?

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:

Do we need bidirectional relations for arbitrary joins?

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.


1 Answers

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.

like image 113
automatix Avatar answered Sep 26 '22 00:09

automatix