Doctrine Class Table Inheritance — нетерпеливо загружает ссылки на подклассы

Рассмотрим следующую диаграмму:
введите описание изображения здесь

Где User имеет много BlogPostх, ан Event это тип BlogPost со свойством Venue,

У меня есть следующие классы сущностей:

**
* @ORM\Entity()
* @ORM\Table(name="User")
*/
class User {
...
/**
* @ORM\OneToMany(targetEntity="BlogPost",mappedBy="User")
* @ORM\JoinColumn(...)
*/
protected $BlogPosts;
...
}

/**
* @ORM\Entity()
* @ORM\Table(name="BlogPost")
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(...)
* @ORM\DiscriminatorMap({...})
* ...
*/
class BlogPost {
...
/**
* @ORM\ManyToOne(targetEntity="User",inversedBy="BlogPosts")
* @ORM\JoinColumn(...)
*/
protected $User
...
}

/**
* @ORM\Entity()
* @ORM\Table(name="Event")
*/
class Event extends BlogPost {
...
/**
* @ORM\ManyToOne(targetEntity="Venue")
* @ORM\JoinColumn(...)
*/
protected $Venue;
...
}

/**
* @ORM\Entity()
* @ORM\Table(name="Venue")
*/
class Venue {
...
}

Теперь я хотел бы создать запрос, который получает события определенных пользователей и активно загружает места событий. Самое близкое, что у меня есть:

$qb = $em->createQueryBuilder();
$qb
->select('User,'BlogPost,Venue')
->from('User','User')
->join('User.BlogPosts','BlogPost','WITH','BlogPost INSTANCE OF :Event')
->join('BlogPost.Venue','Venue')
->setParameter('Event',$em->getClassMetadata('Event'));

Это дает мне довольно предсказуемую ошибку:

Error: Class BlogPost has no association named Venue

Удаление ссылок на Venue Я получу всех пользователей EventЭто просто отлично, но тогда мне придется положиться на ленивую загрузку, чтобы получить остальную часть Eventсвойства.

Я видел предложения, которые я сопоставляю Events в User:

class User {
...
/**
* @ORM\OneToMany(targetEntity="BlogPost",mappedBy="User")
* @ORM\JoinColumn(name="UserID", referenceColumnName="UserID")
*/
protected $BlogPosts;

/**
* @ORM\OneToMany(targetEntity="Event",mappedBy="User")
* @ORM\JoinColumn(name="UserID", referenceColumnName="UserID")
*/
protected $Events;
...
}

При попытке этого генерируемый SQL пытается сделать что-то вроде:

SELECT * FROM User
JOIN Event ON User.id = Event.user_id
JOIN BlogPost ON BlogPost.id = Event.blog_post_id

куда user_id столбец в BlogPost и не Event и, следовательно, ошибки с:

Invalid column name 'user_id'

Как я должен отображать таблицы классов наследуемых ссылок?
Есть ли способ добиться полной загрузки, как я описал?

Мне известно, что я упустил некоторые детали из классов, их отображения и сгенерированного SQL. Пожалуйста, кричите, если некоторые детали помогут разобраться в этом.

редактировать

Это отличается от Наследование в одной таблице (STI) с отношением ManyToOne как для наследования таблиц классов, а не наследования таблиц. Кроме того, меня интересует специфика свойств подкласса, представьте, если в этом примере Video были дополнительные ссылки.

3

Решение

Я нашел способ, который делает то, что я хочу, но я уверен, что должен быть лучший путь.

Сначала напишите собственный запрос:

$sql =<<<SQL
SELECT * FROM User user
JOIN BlogPost blog_post ON user.id = blog_post.UserID
JOIN Event event ON blog_post.id = event.BlogPostID
JOIN Venue venue ON event.VenueID = venue.id
WHERE user.id = ?
SQL;

Это можно либо запустить напрямую через $em->getConnection()->prepare() или еще лучше, используя ResultSetMapping, а затем через $em->createNativeQuery($sql,$rsm)

$rsm = new \Doctrine\ORM\Query\ResultSetMappingBuilder($em);
$rsm->addRootEntityFromClassMetadata('User','user');
$rsm->addIndexBy('user','id');
$rsm->addJoinedEntityResult('event','event','user','BlogPosts');
$rsm->addJoinedEntityResult('venue','venue','event','Venue');
$rsm->addFieldResult(); // add all of the fields you are interested in

$query = $this->get_manager()->createNativeQuery($sql,$rsm);
$query->setParameter(1, $user_id);

return $query->getResult($hydration_mode);

Кажется позором, что это не может быть сделано через QueryBuilder но, насколько я могу судить, это единственный способ достичь этого. Я хотел бы, чтобы меня показали иначе.

0

Другие решения

Других решений пока нет …