महत्वपूर्ण अस्वीकरण: ऐसा करने का उचित तरीका आपकी तालिका संरचना को संशोधित करना नहीं है, बल्कि wp_usermeta का उपयोग करना है। तब आपको अपनी पोस्ट को क्वेरी करने के लिए कोई कस्टम SQL बनाने की आवश्यकता नहीं होगी (हालाँकि आपको अभी भी किसी कस्टम पर्यवेक्षक को रिपोर्ट करने वाले सभी की सूची प्राप्त करने के लिए कुछ कस्टम SQL की आवश्यकता होगी - उदाहरण के लिए, व्यवस्थापक अनुभाग में)। हालाँकि, चूंकि ओपी ने कस्टम एसक्यूएल लिखने के बारे में पूछा था, यहाँ मौजूदा वर्डप्रेस क्वेरी में कस्टम एसक्यूएल को इंजेक्ट करने के लिए सबसे अच्छा अभ्यास है।
यदि आप कॉम्प्लेक्स जॉइन कर रहे हैं, तो आप बस पोस्ट्स-वे फिल्टर का उपयोग नहीं कर सकते, क्योंकि आपको जॉइन, सेलेक्ट, और संभवतः समूह को या क्वेरी के अनुभागों द्वारा आदेश को संशोधित करना होगा।
आपका सबसे अच्छा शर्त 'पोस्ट_क्लॉस' फिल्टर का उपयोग करना है। यह एक अत्यधिक उपयोगी फ़िल्टर है (जिसका दुरुपयोग नहीं किया जाना चाहिए!) जो आपको वर्डप्रेस कोर के भीतर कोड की कई लाइनों द्वारा स्वचालित रूप से उत्पन्न होने वाले SQL के विभिन्न भागों को जोड़ने / संशोधित करने की अनुमति देता है। फ़िल्टर कॉलबैक हस्ताक्षर है:
function posts_clauses_filter_cb( $clauses, $query_object ){ }
और यह आपसे लौटने की उम्मीद करता है $clauses
।
खण्ड
$clauses
एक सरणी है जिसमें निम्नलिखित कुंजियाँ हैं; प्रत्येक कुंजी एक SQL स्ट्रिंग है जिसे डेटाबेस में भेजे गए अंतिम SQL कथन में सीधे उपयोग किया जाएगा:
- कहा पे
- समूह द्वारा
- में शामिल होने के
- द्वारा आदेश
- अलग
- खेत
- सीमा
यदि आप डेटाबेस में एक तालिका जोड़ रहे हैं (केवल ऐसा ही करें यदि आप पूरी तरह से post_meta, user_meta या वर्गीकरणों का लाभ नहीं उठा सकते हैं) तो संभवतः आपको इनमें से एक से अधिक खंडों को छूने की आवश्यकता होगी, उदाहरण के लिए, fields
("SELECT") SQL स्टेटमेंट का हिस्सा), join
(आपके सभी टेबल, आपके "FROM" क्लॉज में से एक के अलावा), और शायद orderby
।
खण्ड को संशोधित करना
ऐसा करने का सबसे अच्छा तरीका है कि $clauses
आप फ़िल्टर से प्राप्त की गई सरणी से प्रासंगिक कुंजी को हटा दें :
$join = &$clauses['join'];
अब, यदि आप संशोधित करते हैं, तो आप $join
वास्तव में सीधे संशोधित $clauses['join']
कर सकते हैं, इसलिए $clauses
जब आप इसे वापस करेंगे तो परिवर्तन होंगे ।
मूल खण्डों का संरक्षण
संभावनाएं हैं (नहीं, गंभीरता से, सुनो) आप मौजूदा एसक्यूएल को संरक्षित करना चाहेंगे जो वर्डप्रेस आपके लिए उत्पन्न करता है। यदि नहीं, तो आपको संभवतः posts_request
इसके बजाय फ़िल्टर को देखना चाहिए - यह डेटाबेस से रवाना होने से ठीक पहले पूर्ण mySQL क्वेरी है, इसलिए आप इसे पूरी तरह से अपने साथ जोड़ सकते हैं। तुमने ऐसा क्यों करना चाहोगे? आप शायद नहीं।
इसलिए, क्लॉज में विद्यमान एसक्यूएल को संरक्षित करने के लिए, क्लॉसेस के लिए अपील करना याद रखें, उन्हें असाइन न करें (यानी: नोट $join .= ' {NEW SQL STUFF}';
न करें $join = '{CLOBBER SQL STUFF}';
। क्योंकि $clauses
सरणी का प्रत्येक तत्व एक स्ट्रिंग है, यदि आप इसे जोड़ना चाहते हैं। आप शायद किसी भी अन्य चरित्र टोकन से पहले एक स्थान सम्मिलित करना चाहते हैं, अन्यथा आप शायद कुछ SQL वाक्यविन्यास त्रुटि पैदा करेंगे।
आप बस मान सकते हैं कि प्रत्येक खंड में हमेशा कुछ होगा, और इसलिए प्रत्येक नए स्ट्रिंग को अंतरिक्ष के साथ शुरू करना याद रखें, जैसे:, $join .= ' my_table
या, आप हमेशा एक छोटी रेखा जोड़ सकते हैं जो केवल एक स्थान जोड़ता है यदि आपको आवश्यकता है:
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' ';
$join .= "JOIN my_table... "; // <-- note the space at the end
$join .= "JOIN my_other_table... ";
return $clauses;
यह एक शैलीगत चीज़ है जो किसी भी चीज़ से अधिक है। याद रखने के लिए महत्वपूर्ण बिट यह है: यदि आप पहले से ही इसमें कुछ एसक्यूएल रखते हैं तो क्लॉज में शामिल होने पर हमेशा अपनी स्ट्रिंग को एक जगह छोड़ दें!
एक साथ रखते हुए
वर्डप्रेस विकास का पहला नियम है कि आप जितना हो सके उतनी मुख्य कार्यक्षमता का उपयोग करने का प्रयास करें। यह आपके काम का भविष्य का सबूत देने का सबसे अच्छा तरीका है। मान लीजिए कि कोर टीम तय करती है कि वर्डप्रेस अब SQLite या Oracle या कुछ अन्य डेटाबेस भाषा का उपयोग करेगा। कोई भी हाथ से लिखा mySQL अमान्य हो सकता है और आपके प्लगइन या थीम को तोड़ सकता है! WP को अपने आप पर जितना संभव हो उतना SQL उत्पन्न करने के लिए बेहतर है, और बस उन बिट्स को जोड़ें जिनकी आपको आवश्यकता है।
तो व्यापार का पहला आदेश WP_Query
आपके आधार क्वेरी के जितना संभव हो उतना उत्पन्न करने के लिए लाभ उठा रहा है। ऐसा करने के लिए हम जिस सटीक तरीके का उपयोग करते हैं, वह काफी हद तक इस बात पर निर्भर करता है कि पदों की यह सूची कहाँ दिखाई देने वाली है। यदि यह पृष्ठ का उप-भाग है (आपकी मुख्य क्वेरी नहीं) तो आप उपयोग करेंगे get_posts()
; यदि यह मुख्य क्वेरी है, तो मुझे लगता है कि आप इसका उपयोग कर सकते हैं query_posts()
और इसके साथ किया जा सकता है, लेकिन ऐसा करने का उचित तरीका डेटाबेस को हिट करने से पहले मुख्य क्वेरी को रोकना है (और सर्वर चक्र का उपभोग करता है) इसलिए request
फ़िल्टर का उपयोग करें ।
ठीक है, इसलिए आपने अपनी क्वेरी तैयार कर ली है और एसक्यूएल बनने वाला है। ठीक है, वास्तव में, इसे बनाया गया है, बस डेटाबेस को नहीं भेजा गया है। posts_clauses
फ़िल्टर का उपयोग करके , आप अपने कर्मचारी संबंध तालिका को मिश्रण में जोड़ने जा रहे हैं। इस तालिका को {$ wpdb-> उपसर्ग} कहते हैं। 'user_relationship', और यह एक प्रतिच्छेदन तालिका है। (वैसे, मेरा सुझाव है कि आप इस तालिका संरचना को सामान्य करें और इसे निम्नलिखित क्षेत्रों के साथ एक उचित चौराहे की तालिका में बदल दें: 'relationship_id', 'user_id', 'related_user_id', 'relationship_type'; यह बहुत अधिक लचीला और शक्तिशाली है। .. लेकिन मैं पीछे हटा)।
यदि मैं समझता हूं कि आप क्या करना चाहते हैं, तो आप एक लीडर की आईडी को पास करना चाहते हैं और फिर उस लीडर के फॉलोअर्स द्वारा केवल पोस्ट देखें। मुझे उम्मीद है कि मुझे वह सही मिला। यदि यह सही नहीं है, तो आपको मेरे कहे अनुसार लेना होगा और इसे अपनी आवश्यकताओं के अनुकूल बनाना होगा। मैं आपकी टेबल संरचना के साथ रहूँगा: हमारे पास एक leader_id
और एक है follower_id
। तो JOIN {$wpdb->posts}.post_author
आपके 'user_relationship' टेबल पर 'follower_id' की विदेशी कुंजी के रूप में होगा ।
add_filter( 'posts_clauses', 'filter_by_leader_id', 10, 2 ); // we need the 2 because we want to get all the arguments
function filter_by_leader_id( $clauses, $query_object ){
// I don't know how you intend to pass the leader_id, so let's just assume it's a global
global $leader_id;
// In this example I only want to affect a query on the home page.
// This is where the $query_object is used, to help us avoid affecting
// ALL queries (since ALL queries pass through this filter)
if ( $query_object->is_home() ){
// Now, let's add your table into the SQL
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' '; // add a space only if we have to (for bonus marks!)
$join .= "JOIN {$wpdb->prefix}employee_relationship EMP_R ON EMP_R.follower_id = {$wpdb->posts}.author_id";
// And make sure we add it to our selection criteria
$where = &$clauses['where'];
// Regardless, you always start with AND, because there's always a '1=1' statement as the first statement of the WHERE clause that's added in by WP/
// Just don't forget the leading space!
$where .= " AND EMP_R.leader_id={$leader_id}"; // assuming $leader_id is always (int)
// And I assume you'll want the posts "grouped" by user id, so let's modify the groupby clause
$groupby = &$clauses['groupby'];
// We need to prepend, so...
if (! empty( $groupby ) ) $groupby = ' ' . $groupby; // For the show-offs
$groupby = "{$wpdb->posts}.post_author" . $groupby;
}
// Regardless, we need to return our clauses...
return $clauses;
}