2017-02-06 14 views
1

私はいくつかの共通のインタフェースを実装しているdoctrineエンティティを持っていますが、(理想的には)doctrineのリポジトリを作成して、単純なSQLで)。エンティティは、共通の基底クラスから継承しません。共通インタフェースを実装するエンティティのDoctrineリポジトリ

具体インタフェースは、オブジェクトがタグとして使用することができます:

interface My\TaggableInterface 
{ 
    // get object UUID 
    public function getObjectIdentity(): string 
    // get the tag text 
    public function getTagString(): string 
} 

class My\Entity implements My\TaggableInterface 

class My\Other\Entity implements My\TaggableInterface 

私は労働組合を管理されたカスタムリポジトリを作成するには期待していたので、私は書くことができます:

$entityManager()->getRepository('My\\TaggableInterface') 
    ->findBy(
     //criteria 
    )` 

しかし、インターフェイスまたはsupport for union in the doctrine query builderから一時テーブルを作成する方法はありません。可能であればネイティブ(私)のSQLの使用を避けたいですが、Doctrineを使用してこれを達成する方法がわかりません。

多くのありがとうございます。

+0

Doctrineのエンティティ間でリポジトリを共有できません。エンティティごとにカスタムリポジトリを作成し、特性やベースリポジトリを介してタグ可能なものを実装することができます。 – Cerad

答えて

1

単一のクエリでは実行できません。たとえあなたが何らかの形でこのクエリを構築することができたとしても、doctrineは結果を水和する方法を知らないでしょう。

ただしそれらにあなたのコード内のすべてのどこかをリストアップすることなく、あなたのインターフェイスを実装するすべてのエンティティを見つけ、照会できます

$result = array(); 
$criteria = array(
    // criteria 
); 
foreach ($em->getMetadataFactory()->getAllMetadata() as $m) { 
    $class = $m->getName(); 
    $reflClass = new \ReflectionClass($class); 
    if ($reflClass->implementsInterface('My\TaggableInterface')) { 
     $result = array_merge($result, $em->getRepository($class)->findBy($criteria)); 
    } 
} 
// results of various entity classes are now all in $result 
+0

これは問題ありませんが、クエリの結果をすべて読み込んでソートされたデータとページ番号が付いたデータを取得することを意味します。私は 'EntityManager :: createNativeQuery'と私が望むもののための' ResultSetMapping'クラスを使用しなければならないと思いますが、これはORMで行うことができる最高のものです。 – avy

+0

残念ながら、ネイティブのSQLとResultSetMappingを使用しても、AFAIKではUNIONクエリからの異なる結果行を異なるエンティティクラスに水和することはできません。私はこの作業をするためには、カスタムヒーターを作成する必要があります(https://techpunch.co.uk/development/create-custom-doctrine2-hydrator-symfony2を参照)。 – aferber

+0

私の場合、彼らはすべてタグエンティティに水和されています。私は新しいタグのIDを作成するためにMySQLの 'UUID()'関数を使いました。もしユーザーがそのタグを保存していれば、本当のタグエンティティと同じように扱うことができます。ちょっと面倒ですが、この場合はうまくいくでしょう。 – avy

0

私が使用したソリューションの概要は以下の通りです。私は各テーブルの結果をタグエンティティ(ユーザーがタグを選択した場合にORMを使用して永続化することができます)に水分補給しているので、複数のエンティティクラスを同じ結果セットから水和する必要はありません。

$sql = <<<EOF 
    SELECT `id`, `text` 
    FROM tag_table 
    GROUP BY `text` 
    UNION 
    SELECT UUID() as `id`, `some_text_field` as `text` 
    FROM another_table 
    GROUP BY `some_text_field` 
EOF; 

$resultMapping = new ResultSetMapping(); 
$resultMapping->addEntityResult('My\Tag\Entity', 'tag'); 
$resultMapping->addFieldResult('tag', 'id', 'id'); 
$resultMapping->addFieldResult('tag', 'text', 'text'); 
$nativeQuery = $entityManager->createNativeQuery($sql, $resultMapping); 

$result = $nativeQuery->getResult(); 

ザSQL次いで、改ページを処理するため、及びテーブルを横切って重複したエントリをすることによって除去されたときにタグエンティティテーブルは、(同じタグテキストの代わりに、新たに生成されたUUIDの)が使用されていることを確認するために拡張することができます連合。

関連する問題