私は自分の問題を解決したと思います。他の誰かがこれらの結果を達成するためのよりエレガントな方法を持っている場合は、遠慮なく説明してください。すべてのクエリを変更するために、カスタム EntityManager とカスタム EntityRepository を作成しました。
カスタム EntityManager で、2 つのメソッドを上書きしました。create() および getRepository()
public static function create($conn, Configuration $config, EventManager $eventManager = null)
{
if ( ! $config->getMetadataDriverImpl()) {
throw ORMException::missingMappingDriverImpl();
}
switch (true) {
case (is_array($conn)):
$conn = \Doctrine\DBAL\DriverManager::getConnection(
$conn, $config, ($eventManager ?: new EventManager())
);
break;
case ($conn instanceof Connection):
if ($eventManager !== null && $conn->getEventManager() !== $eventManager) {
throw ORMException::mismatchedEventManager();
}
break;
default:
throw new \InvalidArgumentException("Invalid argument: " . $conn);
}
return new MyCustomEntityManager($conn, $config, $conn->getEventManager());
}
このメソッドで唯一変更されているのは、独自の EntityManger( MyCustomEntityManager ) を返すことです。次に、次のように getRepository メソッドをオーバーレイしました。
public function getRepository($entityName)
{
$entityName = ltrim($entityName, '\\');
if (isset($this->repositories[$entityName])) {
return $this->repositories[$entityName];
}
$metadata = $this->getClassMetadata($entityName);
$repositoryClassName = $metadata->customRepositoryClassName;
if ($repositoryClassName === null) {
$repositoryClassName = "Acme\DemoBundle\Doctrine\ORM\MyCustomEntityRepository";
}
$repository = new $repositoryClassName($this, $metadata);
$this->repositories[$entityName] = $repository;
return $repository;
}
ここでも、1 行だけ変更しました。DBAL 構成に依存してデフォルトの $repositoryClassName を取得する代わりに、独自のデフォルト リポジトリAcme\DemoBundle\Doctrine\ORM\MyCustomEntityRepositoryを指定しました。
独自のカスタム EntityRepository を作成したら、あとは無限です。次のように、サービスをリポジトリに注入するか (現在、JMS Di アノテーションを使用しています。以下で説明します)、createQueryBuilder メソッドで QueryBuilder に対してカスタム アクションを実行できます。
use JMS\DiExtraBundle\Annotation as DI;
class MyCustomEntityRepository extends EntityRepository
{
private $myService;
public function createQueryBuilder($alias)
{
$queryBuilder = parent::createQueryBuilder($alias);
/** INSERT CUSTOM CODE HERE **/
return $queryBuilder;
}
/**
* @DI\InjectParams({
* "myService" = @DI\Inject("my_service_id")
* })
*/
public function setMyService(MyServiceInterface $myService)
{
$this->myService = $myService;
}
}
独自の EntityRepository を作成したら、このカスタム機能を必要とするすべてのリポジトリで MyCustomEntityRepository を拡張する必要があります。さらに一歩進んで独自の QueryBuilder を作成し、これをさらに拡張することもできます。