JDatabase का उपयोग करके एक उपकुंजी बनाने के लिए विधि


31

पर http://docs.joomla.org/Selecting_data_using_JDatabase , वहाँ एक सबक्वेरी JDatabase का उपयोग कर लिखने के लिए एक दस्तावेज विधि नहीं है।

https://gist.github.com/gunjanpatel/8663333 इसे पूरा करने के एक तरीके का उदाहरण देता है (कुछ बिट्स छोड़ा गया):

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

यह एक अच्छा, प्रशंसनीय दृष्टिकोण की तरह लगता है, लेकिन क्या कोई बेहतर है?


4
आप $ subQuery पर toString () कॉलिंग को छोड़ सकते हैं। जूमला! स्वचालित रूप से आपके लिए इसे संभाल लेगा। इसके अलावा, मैं इसी विधि का उपयोग करता हूं और यह मेरे लिए अच्छा काम कर रहा है।
ज़ाचरी ड्रेपर

यह भी वही विधि है जिसका उपयोग हम com_content में कोर github.com/joomla/joomla-cms/blob/staging/compenders/… पर
जॉर्ज विल्सन

@ZacharyDraper दिलचस्प। क्या आप उस कोड को दिखा सकते हैं जो इसके लिए जिम्मेदार है?
दिमित्री रेकुन

3
@ZacharyDraper: PHP (जूमला के बजाय! प्रति se) इसे आपके लिए संभालती है ( __toString()) एक "जादू" विधि है।
MrWhite

हाँ, धन्यवाद w3d
ज़ाचरी ड्रेपर

जवाबों:


16

हाँ, जहाँ तक मेरा सवाल है, आपने जिस तरह से सब-वे का निर्माण किया है, वह जूमला के अधिकांश एक्सटेंशन डेवलपर्स द्वारा अपनाया गया है।

मैं अपने कुछ एक्सटेंशन और कस्टम एक्सटेंशन क्लाइंट के लिए बना रहा हूं।

ऐसा करने का कोई "आधिकारिक" तरीका नहीं है, लेकिन जैसा कि आपने दिखाया है कि आप क्वेरी बिल्डर का उपयोग करते हैं और अभी भी एक अच्छा देयता बनाए रखते हैं


10

AFAIK आसान उपश्रेणियों को करने के लिए एक अंतर्निहित तरीका नहीं है, जो संभवतः सिस्टम में एक कमी है और पीआर के माध्यम से इसे ठीक किया जाना चाहिए।

हालाँकि, मैं आपके उदाहरण के साथ कोई समस्या नहीं देखता - उचित उचित लगता है।

~~~

नीचे @ DavidFritsch की टिप्पणी के जवाब में एक उदाहरण दिया गया है। हालांकि मैं इसके बारे में जितना अधिक सोचता हूं, ओपी में प्रदर्शित होने वाले अधिक सरल दृष्टिकोण मुझे पसंद हैं। यह अधिक स्पष्ट है कि क्या हो रहा है।

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

1
क्या आपके पास कोई विचार है कि यह कैसे काम किया जा सकता है? मैं उस प्रारूप की कल्पना करने की कोशिश कर रहा हूं जिसका उपयोग आप इस कार्य को एक क्वेरी ऑब्जेक्ट पर करने के लिए करेंगे और वास्तव में इस विधि से आसान कुछ भी नहीं लगता है।
डेविड फ्रिट्स

1
यह एक subQuerySelectविधि बनाने के लिए सार्थक हो सकता है जिसमें यह आपको इसे थोड़ा और "साफ" करने की अनुमति देता है। मैं प्रदान करने और उदाहरण के लिए अपना उत्तर संपादित करूँगा।
डॉन गिल्बर्ट

मैं जूमला में देखना पसंद
करूंगा

3

उन प्रश्नों को निष्पादित करने का एक तरीका भी है जिनमें जूमला प्लेटफॉर्म एपीआई का उपयोग करके उपश्रेणियाँ शामिल हैं। उपकेंद्रों का उपयोग कैसे किया जाए, इस पर मूल विचार बंदूकपनपटेल पर आधारित है ।

यहां नेस्टेड सेट मॉडल पर प्रश्नों को निष्पादित करने के लिए एक उदाहरण है :

SQL क्वेरी:

-- 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;

और जूमला द्वारा निष्पादित की जाने वाली रूपांतरित क्वेरी:

// 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>";

1
अच्छा लग रहा है, लेकिन ओपी के उदाहरण के रूप में बिल्कुल उसी तरह है: पहले उपकुंजी बनाएं और फिर मुख्य क्वेरी में इसका उपयोग करें। सवाल था कि क्या कोई बेहतर तरीका है।
fruppel

1

मैं स्निपेट के अपने संस्करण की पेशकश करूंगा और फिर मेरे औचित्य को समझाऊंगा और जूमला कोडिंग स्टैंडर्ड्स मैनुअल (जो कि कोटाब्लॉक स्वरूपित होगा) के उद्धरण शामिल हैं ।

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

क्वेरी पद्धति का उपयोग करके क्वेरी विधि की एक संख्या को जोड़ने के लिए, एक के बाद एक, प्रत्येक विधि एक ऐसी वस्तु को लौटाती है जो अगली विधि का समर्थन कर सकती है, इससे पठनीयता में सुधार होता है और परिणामी कोड सरल हो जाता है।

  • मैं सबसे पहले क्वेरी लिखता हूं और सबसे बाहरी क्वेरी के लिए प्रगति करता हूं। यह मुझे सभी क्वेरी बिल्डिंग विधियों को सीधे getQuery()विधि की श्रृंखला की अनुमति देता है । प्रभावी रूप से, वैरिएबल नाम केवल व्यक्तिगत क्वेरी बनाते समय एक बार लिखा जाता है।
    यहाँ कुछ भारी क्वेरी घोंसले के शिकार का एक शानदार उदाहरण है (जब मुझे लगा कि यह चेयरिंग एरो को लाइन करने के लिए प्यारा था)।

  • मैं एक ही क्वेरी के भीतर कई select()और / या where()कॉल करने से बचने की कोशिश करता हूं क्योंकि मैंने इसे कम अनुभवी डेवलपर्स के भ्रम के लिए देखा है । चूँकि ये विधियाँ सरणियाँ स्वीकार करती हैं, इसलिए मुझे उन्हें रोजगार देने के लिए अधिक पठनीय और बेहतर कोडिंग अभ्यास लगता है।

  • और अंत में सबसे विवादास्पद विषय ...

    तालिका नाम और तालिका स्तंभों से बचने के लिए तालिका नाम और तालिका स्तंभ नाम हमेशा उद्धरण () विधि में संलग्न होना चाहिए। किसी क्वेरी में चेक किए गए फ़ील्ड मान को हमेशा डेटाबेस से पास करने से पहले मूल्य से बचने के लिए उद्धरण () विधि में संलग्न किया जाना चाहिए। एक क्वेरी में जाँच किए गए पूर्णांक मान भी टाइप (int) में डाले जाने चाहिए।

    मैं इस रुख पर बहुत विवादित हूं। जब मैं पहली बार पिछले साल जुमला में आया था, मैंने सोचा था, मैं बेकार कॉल नहीं कर रहा हूं (स्थैतिक, सुरक्षा, क्वेरी की पठनीयता का कोई लाभ नहीं) स्थिर मूल्यों पर! लेकिन, मेरा नियोक्ता जूमला लाइन पर ही चल के विचार पसंद करती है, और मैं, स्वीकार करने के लिए है कि मैं आम तौर पर नियमों के लिए एक उच्च सराहना की है है तो मैं के साथ मेरी प्रश्नों नीचे hosing कर दिया है quote(), (int)और quoteName()जो भी स्ट्रिंग संयोजन के ढेर का मतलब है (सभी ठीक से रखा हुआ)। मेरे काम के अंतिम परिणाम भयावह रूप से ब्लॉटेड क्वेरी ब्लॉक होते हैं, यहां तक ​​कि मेरे पास एक कठिन समय है। सबसे खराब / सबसे लंबी लाइनें जो खुद को वर्टिकल स्टैकिंग के लिए उधार नहीं देती हैं join(), वे टैबलेन, अलियास, ONऔर फिर एक या एक से अधिक शर्तों के कारण कॉल हैं जिन्हें उद्धृत करने की आवश्यकता हो सकती है या नहीं।मैं इस बात की सराहना कर सकता हूं कि यह नीति नौसिखिया डेवलपर्स के लिए सुरक्षा को ध्यान में रखते हुए लागू की गई है, लेकिन मुझे यकीन है कि अगर यह नीति किसी तरह इस संवेदनशीलता के साथ सम्‍मिलित थी कि सभी जूमला कोडर अज्ञानी कॉपी-पास्‍टर नहीं हैं। मेरा मतलब है, इस बात पर ध्यान दें कि अनावश्यक कॉल के बिना कोड कितना साफ और संक्षिप्त है।

  • मोपिंग के लिए:

    • मैं *अपने सेलेक्ट क्लॉस में लगभग कभी भी इस्तेमाल नहीं करता
    • मैं कभी फोन नहीं करता __toString()
    • मैं पूर्णांकों को उद्धृत नहीं करता, मैंने उन्हें पूर्णांक के रूप में रखा
    • मैं नहीं लिखता ASCक्योंकि वह डिफ़ॉल्ट सॉर्टिंग दिशा है
    • मैं नए टेबल नाम और कॉलम नाम बनाते समय mysql कीवर्ड का उपयोग नहीं करने का हर संभव प्रयास करता हूं
    • व्यक्तिगत पसंद के विषय के रूप में, मैं एकरूपता बनाए रखने के लिए अपने तरीके के स्ट्रिंग तर्कों पर दोहरे उद्धरण का उपयोग करता हूं, mysql के एकल उद्धरण से अलग करता हूं, और ताकि मैं चर प्रक्षेप का आनंद ले सकूं जिसे मैं " जटिल वाक्य रचना " के साथ लिखता हूं ।
    • मैं जानकारीपूर्ण चर नामों का उपयोग करता हूं और अपने नेस्टेड प्रश्नों की पठनीयता और आमतौर पर मेरे कोड की सहायता के लिए टिप्पणी करता हूं
    • अपनी हिरासत छोड़ने से पहले मैं अपने कोड का परीक्षण करता हूं
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.