سؤال

أنا أستخدم PHP Doctrine ORM لبناء استعلاماتي.ومع ذلك، لا يمكنني معرفة كيفية كتابة عبارة WHERE التالية باستخدام DQL (لغة استعلام العقيدة):

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

والتي، بسبب ترتيب العمليات، لا تُرجع النتائج المقصودة.

أيضًا، هل هناك فرق بين طرق "أين" و"وأين" و"أد أين"؟

تحديثحسنًا، يبدو أنه لا يمكنك إجراء استعلامات معقدة باستخدام 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)");
هل كانت مفيدة؟

المحلول

من تجربتي، كل مجمع 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

نصائح أخرى

يمكن العثور على الطريقة الصحيحة للقيام بذلك على العقيدة 2 - الاستعلامات الشرطية لمنشئ الاستعلام...إذا تصريحات؟ كما أشار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);

نظرًا لأنه يبدو أنه لا يمكنك إجراء استعلامات معقدة باستخدام DQL، فقد كتبت SQL التالي لتمريرها إلى طريقة andWhere():

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

لاحظ "وصحيح"، وهو اختراق حتى لا يتجاهل المحلل اللغوي الأقواس الخارجية.

وحيث يمكن تلخيصها على النحو التالي:
تمت إضافة الشرط (الشروط) مسبقًا إلى بيان "أين".

يمكنك استخدامها بأمان و أين بدلا من أين.(يقدم حملًا صغيرًا جدًا، وهو مذكور أدناه في عنصر القائمة الثاني.)

تنفيذ وأين هو:(العقيدة 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. ألحق و بيان ل أين جزء من الاستعلام، إذا تمت إضافة بيان آخر من قبل
  3. إلحاق الشرط

أما بالنسبة للفرق بين أين وأين وأدوير، فلا أعتقد أن هناك اختلافًا كبيرًا عن آخر مرة قرأت فيها المصدر.ومع ذلك، أود أن أشجعك على قراءة مصدر العقيدة.إنه أمر بسيط حقًا، ويساعد في ملء الثغرات الموجودة في الوثائق (هناك الكثير).أما بالنسبة للعبارات المعقدة، فقد تساءلت عن ذلك بنفسي ولكن لم تكن لدي حاجة إليها بعد.

من خلال تجربتي، رأيت أحيانًا فرقًا بين:

$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)");

العبارة الأولى مكتوبة على ثلاثة أسطر، والثانية على سطر واحد فقط.لم أصدق ذلك ولكن هناك فرق!

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

هل تتفضل بتجربة هذا البديل، ولست متأكدًا مما إذا كان يعمل، ولكنه يستحق التجربة

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top