web-dev-qa-db-ja.com

PHP Doctrine ORMを使用した複雑なWHERE句

PHP Doctrine ORMを使用してクエリを作成しています。しかし、DQLを使用して次のWHERE句を記述する方法を理解できていないようです(Doctrineクエリ言語):

WHERE name='ABC' AND (category1 = 'X' OR category2 = 'X' OR category3 = 'X') 
AND price > 10

括弧がどこに行くかをどのように指定できますか?

私が現在持っているものはPHPコードはこれです:

->where('name = ?', 'ABC')
->andWhere('category1 = ?', 'X')
->orWhere('category2 = ?', 'X')
->orWhere('category3 = ?', 'X')
->andWhere('price > ?', 10)

しかし、これは次のようなものを生成します

WHERE name='ABC' AND category1 = 'X' OR category2 = 'X' OR category3 = 'X' 
AND price > 10

操作の順序により、意図した結果が返されません。

また、「where」、「andWhere」、および「addWhere」メソッドに違いはありますか?

[〜#〜] update [〜#〜]わかりました、DQLを使用して複雑なクエリを実行できないようなので、SQLを手動で記述してandWhere()を使用しようとしています追加するメソッド。しかし、私はWHERE..INを使用しており、Doctrineは私の囲み括弧を取り除いているようです:

$q->andWhere("(category1 IN $subcategory_in_clause
            OR category2 IN $subcategory_in_clause 
            OR category3 IN $subcategory_in_clause)");
39
Wickethewok

私の経験から、複雑なwhere関数はそれぞれ括弧内にグループ化されています(Doctrine 1.2.1を使用しています)。

$q->where('name = ?', 'ABC')
  ->andWhere('category1 = ? OR category2 = ? OR category3 = ?', array('X', 'X', 'X'))
  ->andWhere('price < ?', 10)

次のSQLを生成します。

WHERE name = 'ABC' 
  AND (category1 = 'X' OR category2 = 'X' OR category3 = 'X')
  AND price < 10
68
anushr

これを行う正しい方法は doctrine 2-クエリビルダーの条件付きクエリ... Ifステートメント? にあり、@ Jekisが指摘しています。 @anushrの例のように、式ビルダーを使用してこれを解決する方法を次に示します。

$qb->where($qb->expr()->eq('name', ':name'))
  ->andWhere(
    $qb->expr()->orX(
      $qb->expr()->eq('category1', ':category1'),
      $qb->expr()->eq('category2', ':category2'),
      $qb->expr()->eq('category3', ':category3')
  )
  ->andWhere($qb->expr()->lt('price', ':price')
  ->setParameter('name', 'ABC')
  ->setParameter('category1', 'X')
  ->setParameter('category2', 'X')
  ->setParameter('category3', 'X')
  ->setParameter('price', 10);
18
David Baucum

andWhereは次のように要約できます。
以前に追加された条件に対応したWHEREステートメント

whereの代わりにandWhereを安全に使用できます。 (非常に小さなオーバーヘッドが発生します。これは、2番目のリスト項目で後述します。)

AndWhereの実装:(Doctrine 1.2.3)

public function andWhere($where, $params = array())
{
    if (is_array($params)) {
        $this->_params['where'] = array_merge($this->_params['where'], $params);
    } else {
        $this->_params['where'][] = $params;
    }

    if ($this->_hasDqlQueryPart('where')) {
        $this->_addDqlQueryPart('where', 'AND', true);
    }

    return $this->_addDqlQueryPart('where', $where, true);
}

これは、

  1. プロセスパラメーター
  2. [〜#〜]および[〜#〜]ステートメントをクエリのwhere部分に追加別の場合ステートメントが前に追加された場所
  3. 追加条件
1
Lashae

DQLを使用して複雑なクエリを実行することはできないようなので、私はandWhere()メソッドに渡す次のSQLを書きました。

$q->andWhere("(category1 IN $subcategory_in_clause
OR category2 IN $subcategory_in_clause 
OR category3 IN $subcategory_in_clause) AND TRUE");

パーサーが外側の括弧を無視しないようにするためのハックである「AND TRUE」に注意してください。

1
Wickethewok

Whereとwhereとaddwhereの違いについては、最後にソースを読んだときと大きな違いはないと思います。 Doctrineソースを参照することをお勧めします。これは非常にシンプルで、ドキュメントの穴を埋めるのに役立ちます(多数あります)。複雑なwhereステートメントについては、これは私自身ですが、まだそれを必要としていません。

0
Bob Gettys

私の経験では、時々以下の違いを見ました:

$q->andWhere("(category1 IN $subcategory_in_clause
            OR category2 IN $subcategory_in_clause 
            OR category3 IN $subcategory_in_clause)");

そして

$q->andWhere("(category1 IN $subcategory_in_clause OR category2 IN $subcategory_in_clause OR category3 IN $subcategory_in_clause)");

最初のステートメントは3行で記述され、2番目のステートメントは1行だけで記述されます。信じられませんでしたが、IS A DIFFERENCE!

0
baboush
$q->andWhere("category1 IN ( $subcategory_in_clause )
              OR category2 IN ( $subcategory_in_clause )
              OR category3 IN ( $subcategory_in_clause )");

このバリアントを試してみて、うまくいくかどうかはわかりませんが、試してみる価値はありますか

0
T. Kelher