it-swarm-tr.com

JDatabase kullanarak bir alt sorgu oluşturma yöntemi

http://docs.joomla.org/Selecting_data_using_JDatabase adresinde, JDatabase kullanarak bir alt sorgu yazmak için belgelenmiş bir yöntem yoktur.

https://Gist.github.com/gunjanpatel/86633 bunu gerçekleştirmenin bir yolunu gösterir (birkaç bit atlanmıştır):

$subQuery = $db->getQuery(true);
$query    = $db->getQuery(true);

// Create the base subQuery select statement.
$subQuery->select('*')
    ->from($db->quoteName('#__sub_table'))
    ->where($db->quoteName('subTest') . ' = ' . $db->quote('1'));

// Create the base select statement.
$query->select('*')
    ->from($db->quoteName('#__table'))
    ->where($db->quoteName('state') . ' = ' . $db->quote('1'))
    ->where($db->quoteName('subCheckIn') . ' IN (' . $subQuery->__toString() . ')')
    ->order($db->quoteName('ordering') . ' ASC');

// Set the query and load the result.
$db->setQuery($query);

Bu iyi ve makul bir yaklaşım gibi gözüküyor, ama daha iyi bir yaklaşım var mı?

31
betweenbrain

Evet, söz konusu olduğunda, alt sorguyu oluşturma şekliniz, joomla'nın uzantı geliştiricilerinin çoğunluğu tarafından kabul edilen yöntemdir.

Aynı yöntemi bazı uzantılarım ve istemciler için yapılmış özel uzantılarımda kullanıyorum.

Bunu yapmanın "resmi" bir yolu yoktur, ancak gösterdiğiniz gibi yapmak, sorgu oluşturucuyu kullanmanıza ve yine de iyi miktarda okunabilirliği korumanıza olanak tanır

16
Skullbock

AFAIK, kolay alt sorgular yapmak için yerleşik bir yöntem değildir, bu muhtemelen sistemdeki bir eksikliktir ve PR aracılığıyla düzeltilmelidir.

Ancak, örneğinizle ilgili bir sorun görmüyorum - yeterince makul görünüyor.

~~~

Aşağıda @ DavidFritsch'in yorumuna yanıt olarak bir örnek verilmiştir. Bununla birlikte ne kadar çok düşünürsem, OP'de gösterilen daha basit yaklaşımı daha iyi seviyorum. Neler olduğu daha açık.

$query = $this->db->getQuery(true)
  ->select('a.*')
  ->subQuery()
    ->select('b.*')
    ->from('#__table_b AS b')
    ->as('subQueryResult')
  ->endSubQuery()
  ->from('#__table_a AS a');
10
Don Gilbert

Joomla Platform API'sını kullanarak alt sorgular içeren sorguları yürütmenin bir yolu da vardır. Alt sorguların nasıl kullanılacağına dair temel fikir gunjanpatel .

İç İçe Ayarlanmış Modeller üzerindeki sorguları yürütmek için bir örnek:

SQL sorgusu:

-- Find the Immediate Subordinates of a Node
SELECT node.title, (COUNT(parent.id) - (sub_tree.depth + 1)) AS depth
FROM lubd3_usergroups AS node,
        lubd3_usergroups AS parent,
        lubd3_usergroups AS sub_parent,
        (
                SELECT node.id, (COUNT(parent.id) - 1) AS depth
                FROM lubd3_usergroups AS node,
                        lubd3_usergroups AS parent
                WHERE node.lft BETWEEN parent.lft AND parent.rgt
                        AND node.id = 1
                GROUP BY node.id
                ORDER BY node.lft
        )AS sub_tree
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt
        AND sub_parent.id = sub_tree.id
GROUP BY node.id
-- not showing the parent node
HAVING depth = 1
-- showing the parent node
-- HAVING depth <= 1
ORDER BY node.lft;

ve Joomla tarafından yürütülecek dönüştürülmüş sorgu:

// Create the subQuery select statement.
// Nested Set Queries: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
// CROSS JOIN: http://www.informit.com/articles/article.aspx?p=30875&seqNum=5
$subQuery->select(array('node.id', '(COUNT(parent.id) - 1) AS depth'))
    ->from($db->quoteName('#__usergroups') . 'node')
    ->join('CROSS', $db->quoteName('#__usergroups', 'parent'))
    ->where($db->quoteName('node.lft') . ' BETWEEN  ' . $db->quoteName('parent.lft') . ' AND ' . $db->quoteName('parent.rgt') . ' AND ' . $db->quoteName('node.id') . ' = ' . $db->quote('1'))
    ->group($db->quoteName('node.id'))
    ->order($db->quoteName('node.lft'));

// Create the base select statement.
$query->select(array('node.title', '(COUNT(parent.id) - (sub_tree.depth + 1)) AS depth'))
    ->from($db->quoteName('#__usergroups') . 'node')
    ->join('CROSS', $db->quoteName('#__usergroups', 'parent'))
    ->join('CROSS', $db->quoteName('#__usergroups', 'sub_parent'))
    ->join('CROSS', '(' . $subQuery .') AS sub_tree')
    ->where($db->quoteName('node.lft') . ' BETWEEN  ' . $db->quoteName('parent.lft') . ' AND ' . $db->quoteName('parent.rgt')
    . ' AND ' . $db->quoteName('node.lft') . ' BETWEEN  ' . $db->quoteName('sub_parent.lft') . ' AND ' . $db->quoteName('sub_parent.rgt')
    . ' AND ' . $db->quoteName('sub_parent.id') . ' = ' . $db->quoteName('sub_tree.id'))
    ->group($db->quoteName('node.id'))
    ->having($db->quoteName('depth') . ' = ' . $db->quote('1'))
    ->order($db->quoteName('node.lft'));

// Set the query and load the result.
$db->setQuery($query);
$rowList = $db->loadAssocList();

echo "<pre>";
print_r($rowList);
echo "</pre>";
3
Mario Neubauer

Parçacığın versiyonunu sunacağım ve gerekçemi açıklayacağım ve Joomla Kodlama Standartları kılavuz ("queblock biçimlendirilmiş") tırnak işaretleri sunacağım.

$subquery = $db->getQuery(true)
    ->select("checkin")
    ->from("#__sub_table")
    ->where("subTest = 1");

$query = $db->getQuery(true)
    ->select("*")
    ->from("#__table")
    ->where([
        "state = 1",
        "subCheckIn IN ({$subQuery})"
    ])
    ->order("ordering");

$db->setQuery($query);

Sorgu zincirini, bir dizi sorgu yöntemini birbiri ardına bağlamak için kullanın, her yöntem bir sonraki yöntemi destekleyebilen bir nesne döndürür, Bu, okunabilirliği artırır ve ortaya çıkan kodu basitleştirir.

  • İlk olarak en içteki sorguları yazıyorum ve en dıştaki sorguya ilerliyorum. Bu, tüm sorgu oluşturma yöntemlerini doğrudan getQuery() yöntemine zincirlememe izin veriyor. Etkili olarak, değişken adı tek bir sorgu oluşturulurken yalnızca bir kez yazılır.
    İşte bazı ağır sorgu yuvalamalarının müthiş bir örneği (zincirleme okları sıralamanın sevimli olduğunu düşündüğümde).

  • Aynı sorgu içinde birden fazla select() ve/veya where() çağrısı yapmaktan kaçınmaya çalışıyorum çünkü bunu gördüm daha az deneyimli geliştiricilerin karışıklığına yol açıyor . Bu yöntemler dizileri kabul ettiğinden, bunları kullanmak için daha okunabilir ve daha iyi kodlama uygulamaları buluyorum.

  • ve son olarak en tartışmalı konu ...

    Tablo adları ve tablo sütun adları, tablo adından ve tablo sütunlarından kaçmak için her zaman quoteName () yöntemine eklenmelidir. Sorguda işaretlenen alan değerleri, veritabanına iletilmeden önce değerden kaçmak için her zaman quote () yöntemine eklenmelidir. Bir sorguda kontrol edilen tamsayı alan değerleri de (int) türüne dökülmelidir.

    Bu duruş konusunda çok çatıştım. Geçen yıl Joomla'ya ilk geldiğimde, statik değerlerde işe yaramaz çağrılar yapmayacağım (sorgunun istikrarı, güvenliği, okunabilirliği için hiçbir fayda sağlamayacağım)! Ancak, işverenim Joomla hattına ayak basma fikrini seviyor ve genellikle kurallar için büyük bir takdir duyduğumu itiraf etmeliyim, bu yüzden quote(), (int) ve quoteName(), aynı zamanda dize birleştirme yığınları anlamına gelir (tümü uygun aralıklarla). Çalışmamın son sonuçları korkunç bir şekilde şişirilmiş sorgu blokları olan ve hatta gözbebekimde zorlandım. Dikey istiflemeye borç vermeyen en kötü/en uzun hatlar, tablename, diğer ad, ON, daha sonra gerektirebilecek veya gerekmeyebilecek bir veya daha fazla koşul nedeniyle join() çağrılarıdır. alıntı yapmak. Bu politikanın acemi geliştiriciler için güvenlik göz önünde bulundurularak uygulandığını takdir edebilirim, ancak bu politikanın bir şekilde tüm Joomla kodlayıcılarının cahil kopyacı olmama duyarlılığıyla temperlenmesi durumunda eminim Yani, gereksiz aramalar olmadan kodun ne kadar temiz ve kısa göründüğüne bir göz atın.

  • Silme gelince:

    • SELECT deyimlerimde neredeyse hiç * Kullanmıyorum
    • Hiç __toString() çağrmıyorum
    • Tamsayı alıntılamıyorum, tamsayı olarak atıyorum
    • ASC yazmıyorum çünkü bu varsayılan sıralama yönü
    • Yeni tablo adları ve sütun adları oluştururken mysql anahtar sözcüklerini kullanmamak için her türlü çabayı gösteriyorum
    • Kişisel tercih meselesi olarak, tekdüzeliği korumak, mysql'in tek alıntısından ayırt etmek ve tipik olarak yazdığım değişken enterpolasyonun keyfini çıkarmak için yöntemimin dize argümanlarında çift tırnak kullanma eğilimindeyim " karmaşık sözdizimi ".
    • İç içe geçmiş sorgularımın okunabilirliğine yardımcı olmak için bilgilendirici değişken adları ve yorum kullanıyorum ve genel olarak kodum
    • Kodumu gözaltımdan çıkmadan test ediyorum
1
mickmackusa