23

私には2つのクラスがあります-PageとSiteVersionは、多対多の関係があります。SiteVersionのみが関係を認識します(サイトはモジュール式であり、SiteVersionが属するモジュールを削除してドロップできるようにしたいため)。

したがって、SiteVersionの基準に基づいてページを選択するにはどうすればよいですか?

たとえば、これは機能しません。

SELECT p FROM SiteVersion v JOIN v.pages p WHERE v.id = 5 AND p.slug='index'

エラーが発生します:

[Doctrine\ORM\Query\QueryException]
[Semantical Error] line 0, col -1 near 'SELECT p FROM': Error: Cannot select entity through identification variables without choosing at least one root entity alias.

このクエリで「v」を選択できますが。

リレーションシップのクラス(PageToVersionクラス)を導入することでこれを解決できると思いますが、それを行わない、または双方向にする方法はありますか?

4

5 に答える 5

29

DoctrineORMでこれを処理する方法は2つあります。最も一般的なものはIN、サブクエリで条件を使用することです。

SELECT
    p
FROM
    SitePage p
WHERE
    p.id IN(
        SELECT
            p2.id
        FROM
            SiteVersion v
        JOIN
            v.pages p2
        WHERE
            v.id = :versionId
            AND
            p.slug = :slug
    )

もう1つの方法は、ORMのバージョン2.3で導入された任意の結合機能を使用した追加の結合です。

SELECT
    p
FROM
    SitePage p
JOIN
    SiteVersion v
WITH
    1 = 1
JOIN
    v.pages p2
WHERE
    p.id = p2.id
    AND
    v.id = :versionId
    AND
    p2.slug = :slug

これ1 = 1は、パーサーの現在の制限によるものです。

セマンティックエラーの原因となる制限は、ハイドレーションプロセスが選択したエンティティのルートから開始されるためであることに注意してください。ルートが設定されていない場合、ハイドレーターはフェッチ結合または結合された結果を折りたたむ方法について参照できません。

于 2013-03-16T01:53:32.830 に答える
1

これ(またはそのようなもの)を試してください:

SELECT p FROM Page p WHERE EXISTS (SELECT v FROM SiteVersion v WHERE p MEMBER OF v.pages AND v.id = 5 AND p.slug = 'index')

私はこれを正確にテストしていませんが、仕事に似たものを手に入れました。EXISTSおよびの使用は、DQLの章のDQLSelectExamplesセクションに埋め込まMEMBER OFれています。

于 2012-07-11T22:44:17.403 に答える
1

ネイティブ クエリを機能させる方法がわからなかったので、少しハックな方法で解決しました。

$id = $em->getConnection()->fetchColumn("SELECT
    pages.id
    FROM
    pages
    INNER JOIN siteversion_page ON siteversion_page.page_id = pages.id
    INNER JOIN siteversions ON siteversion_page.siteversion_id = siteversions.id
    WHERE siteversions.id = 1
    AND pages.slug = 'index'");

$page = $em->find('Page', $id);

データベースへのクエリが増えるため(特に、1つではなくページの配列を取得する必要がある場合)、私はそれが好きではありませんが、機能します。

編集:協会のクラスを使用することにしました。これで、次のクエリを実行できます。

SELECT p FROM Page p, SiteVersionPageLink l
WHERE l.page = p AND l.siteVersion = 5 AND p.slug = 'index'
于 2011-03-25T14:51:18.757 に答える
1

クエリでも SiteVersion を選択する必要があると思います。

SELECT v, p FROM SiteVersion v JOIN v.pages p WHERE v.id = 5 AND p.slug='index'

Page エンティティを取得するためにループできる SiteVersion エンティティの配列を取得します。

于 2011-03-25T17:08:39.157 に答える
0

この問題の可能な解決策をここで見つけました。

そのページによると、クエリは次のようになります。

SELECT p FROM SiteVersion v, Page p WHERE v.id = 5 AND p.slug='index' AND v.page = p;

それはあなたの問題を解決しますか?

于 2011-03-25T12:42:22.360 に答える