क्वेरी में कस्टम तालिका शामिल करने के लिए WP_Query का विस्तार कैसे करें?


31

मुझे इस मुद्दे पर अब कई दिन हो गए हैं। प्रारंभ में, यह था कि किसी उपयोगकर्ता के फॉलोअर डेटा को डेटाबेस में कैसे स्टोर किया जाए, जिसके लिए मुझे वर्डप्रेस आंसर की में कुछ अच्छी सिफारिशें मिलीं। सिफारिशों के बाद, मैंने इस तरह एक नई तालिका जोड़ी है:

id  leader_id   follower_id
1   2           4
2   3           10
3   2           10

ऊपर दी गई तालिका में, पहली पंक्ति में 2 की आईडी वाला एक उपयोगकर्ता है, जिसे 4. की आईडी के साथ एक उपयोगकर्ता द्वारा चलाया जा रहा है। दूसरी पंक्ति में, एक आईडी के साथ 3 के साथ एक उपयोगकर्ता का आईडी है। 10. 10. तीसरी पंक्ति के लिए एक ही तर्क लागू होता है।

अब, अनिवार्य रूप से मैं WP_Query का विस्तार करना चाहता हूं ताकि मैं किसी उपयोगकर्ता के नेता (केवल) द्वारा प्राप्त पदों को सीमित कर सकूं। इसलिए, उपरोक्त तालिका को ध्यान में रखते हुए, अगर मुझे उपयोगकर्ता आईडी 10 को WP_Query में पारित करना था, तो परिणाम केवल उपयोगकर्ता आईडी 2 और उपयोगकर्ता आईडी 3 द्वारा पोस्ट होना चाहिए।

मैंने उत्तर खोजने की बहुत कोशिश की है। न ही, मैंने WP_Query वर्ग का विस्तार करने के तरीके को समझने में मेरी मदद करने के लिए कोई ट्यूटोरियल देखा है। मैंने माइक शिंकेल के उत्तरों (WP_Query का विस्तार) को इसी तरह के प्रश्नों के लिए देखा है, लेकिन मुझे वास्तव में समझ नहीं आया है कि इसे अपनी आवश्यकताओं के लिए कैसे लागू किया जाए। यह बहुत अच्छा होगा अगर कोई मेरी मदद कर सके।

माइक के जवाब के लिए अनुरोध के अनुसार लिंक : लिंक 1 , लिंक 2


कृपया Mikes के उत्तर के लिए एक लिंक जोड़ें।
कैसर

1
क्या आप इस बात का उदाहरण दे सकते हैं कि आप किसके लिए क्वेरी कर रहे हैं? WP_Queryपोस्ट प्राप्त करने के लिए है, और मैं यह समझने में असफल हूं कि यह पोस्टों से कैसे जुड़ा है।
mor7ifer

@kaiser ने माइक के उत्तरों के साथ प्रश्न को अद्यतन किया है।
जॉन

@ m0r7if3r »मैं WP_Query का विस्तार करना चाहता हूं ताकि मैं केवल उस उपयोगकर्ता के नेता (नों) द्वारा प्राप्त पदों को सीमित कर सकूं, इसलिए" लेखक द्वारा पोस्ट प्राप्त करना "के समान है।
कैसर

2
@ m0r7if3r पोस्ट बिल्कुल वही है जो मुझे क्वेरी के लिए चाहिए। लेकिन प्राप्त किए जाने वाले पद उन उपयोगकर्ताओं द्वारा होने चाहिए जो कस्टम तालिका में एक निश्चित उपयोगकर्ता के नेता के रूप में सूचीबद्ध हैं। इसलिए, दूसरे शब्दों में, मैं WP_Query को बताना चाहता हूं, सभी पोस्ट उन सभी उपयोगकर्ताओं द्वारा प्राप्त करें जो कस्टम तालिका में ID '10' वाले उपयोगकर्ता के नेता के रूप में सूचीबद्ध हैं।
जॉन

जवाबों:


13

महत्वपूर्ण अस्वीकरण: ऐसा करने का उचित तरीका आपकी तालिका संरचना को संशोधित करना नहीं है, बल्कि 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;
}

13

मैं इस सवाल का जवाब बहुत देर से दे रहा हूं और इसके लिए मेरी माफी भी। मैं इस में भाग लेने के लिए समय सीमा के साथ बहुत व्यस्त हो गया था।

आधार समाधान प्रदान करने में @ m0r7if3r और @kaiser का एक बड़ा धन्यवाद, जिसे मैं अपने आवेदन में विस्तारित और कार्यान्वित कर सकता हूं। यह उत्तर @ m0r7if3r और @kaiser द्वारा प्रस्तावित समाधान के मेरे अनुकूलन पर विवरण प्रदान करता है।

सबसे पहले, मैं समझाता हूं कि यह प्रश्न पहले स्थान पर क्यों पूछा गया था। सवाल और टिप्पणियों के बाद से कोई भी इकट्ठा हो सकता है कि मैं सभी उपयोगकर्ताओं (नेताओं) द्वारा पोस्ट खींचने के लिए WP_Query प्राप्त करने की कोशिश कर रहा हूं जो किसी दिए गए उपयोगकर्ता (अनुयायी) का अनुसरण करता है। अनुयायी और नेता के बीच संबंध एक कस्टम तालिका में संग्रहीत किया जाता है follow। इस समस्या का सबसे आम समाधान फॉलो टेबल से एक फॉलोअर के सभी नेताओं की यूजर आईडी को खींचकर एक एरे में रखना है। निचे देखो:

global $wpdb;
$results = $wpdb->get_results($wpdb->prepare('SELECT leader_id FROM cs_follow WHERE follower_id = %s', $user_id));

foreach($results as $result)
    $leaders[] = $result->leader_id;

एक बार जब आपके पास नेताओं का सरणी हो तो आप इसे WP_Query के तर्क के रूप में पारित कर सकते हैं। निचे देखो:

if (isset($leaders)) $authors = implode(',', $leaders); // Necessary as authors argument of WP_Query only accepts string containing post author ID's seperated by commas

$args = array(
    'post_type'         => 'post',
    'posts_per_page'    => 10,
    'author'            => $authors
);

$wp_query = new WP_Query( $args );

// Normal WordPress loop continues

उपरोक्त समाधान मेरे इच्छित परिणाम प्राप्त करने का सबसे सरल तरीका है। हालांकि, यह गैर-स्केलेबल है। आपके पास दसियों और हजारों नेताओं का अनुसरण करने वाला पल होता है और लीडर आईडी का परिणाम सरणी बहुत बड़ा होता है और आपके वर्डप्रेस साइट को प्रत्येक पेज लोड पर 100MB - 250MB मेमोरी का उपयोग करने के लिए मजबूर करता है और अंततः साइट को क्रैश कर देता है। समस्या का समाधान डेटाबेस पर सीधे SQL क्वेरी चलाने और प्रासंगिक पोस्ट लाने के लिए है। जब @ m0r7if3r का समाधान बचाव में आया। @ केसर की सिफारिश के बाद मैंने दोनों कार्यान्वयन का परीक्षण करने के लिए निर्धारित किया। मैंने वर्डप्रेस के नए परीक्षण इंस्टॉल पर उन्हें पंजीकृत करने के लिए एक सीएसवी फ़ाइल से लगभग 47K उपयोगकर्ताओं को आयात किया। इंस्टॉल ट्वेंटी इलेवन थीम चला रहा था। इसके बाद मैंने लगभग 50 उपयोगकर्ताओं को हर दूसरे उपयोगकर्ता का अनुसरण करने के लिए लूप के लिए दौड़ाया। @Kaiser और @ m0r7if3r के समाधान के लिए क्वेरी के समय में अंतर बहुत ही अधिक था। @ kaiser के समाधान में सामान्यतः प्रत्येक क्वेरी के लिए लगभग 2 से 5 सेकंड लगते थे। मेरे द्वारा उपयोग की जाने वाली भिन्नता बाद में उपयोग के लिए वर्डप्रेस कैश क्वेरी के रूप में होती है। दूसरी ओर @ m0r7if3r के समाधान ने औसतन 0.02 ms के क्वेरी समय का प्रदर्शन किया। दोनों समाधानों के परीक्षण के लिए मैंने लीडर_आईडी कॉलम के लिए अनुक्रमण किया था। अनुक्रमण के बिना क्वेरी समय में एक नाटकीय वृद्धि हुई थी।

सरणी आधारित समाधान का उपयोग करते समय मेमोरी का उपयोग लगभग 100-150 एमबी तक होता है और प्रत्यक्ष SQL चलाते समय 20 एमबी तक गिर जाता है।

मैं @ m0r7if3r के समाधान के साथ एक टक्कर मारता हूं, जब मुझे follow_s को पोस्ट_ प्लेस फ़िल्टर फ़ंक्शन को पास करने की आवश्यकता होती है। मेरे ज्ञान के अनुसार, कम से कम वर्डप्रेस वर्डप्रेस फाइलर फ़ंक्शंस के लिए एक वैरिएबल पास करने की अनुमति नहीं देता है। आप हालांकि वैश्विक चर का उपयोग कर सकते हैं, लेकिन मैं ग्लोबल्स से बचना चाहता था। मैंने अंत में इस मुद्दे को संबोधित करने के लिए WP_Query का विस्तार किया। तो यहाँ अंतिम समाधान है जिसे मैंने लागू किया (@ m0r7if3r के समाधान पर आधारित)।

class WP_Query_Posts_by_Leader extends WP_Query {
    var $follower_id;

    function __construct($args=array()) {
        if(!empty($args['follower_id'])) {
            $this->follower_id = $args['follower_id'];
            add_filter('posts_where', array($this, 'posts_where'));
        }

        parent::query($args);
    }

    function posts_where($where) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'follow';
        $where .= $wpdb->prepare(" AND post_author IN (SELECT leader_id FROM " . $table_name . " WHERE follower_id = %d )", $this->follower_id);
        return $where;
    }
}


$args = array(
    'post_type'         => 'post',
    'posts_per_page'    => 10,
    'follower_id'       => $follower_id
);

$wp_query = new WP_Query_Posts_by_Leader( $args );

नोट: मैंने अंततः उपरोक्त तालिका में 1.2 मिलियन प्रविष्टियों के साथ उपरोक्त समाधान की कोशिश की। औसत क्वेरी समय लगभग 0.060 एमएस था।


3
मैंने आपको कभी नहीं बताया कि मैंने इस सवाल पर चर्चा की कितनी सराहना की। अब जब मुझे पता चला कि मैं इसे याद कर रहा हूं, तो मैंने एक उभार जोड़ा है :)
kaiser

8

आप posts_whereफ़िल्टर का उपयोग करके पूरी तरह से SQL समाधान के साथ कर सकते हैं । यहाँ इसका एक उदाहरण दिया गया है:

if( some condition ) 
    add_filter( 'posts_where', 'wpse50305_leader_where' );
    // lol, question id is the same forward and backward

function wpse50305_leader_where( $where ) {
    $where .= $GLOBALS['wpdb']->prepare( ' AND post_author '.
        'IN ( '.
            'SELECT leader_id '.
            'FROM custom_table_name '.
            'WHERE follower_id = %s'.
        ' ) ', $follower_id );
    return $where;
}

मुझे लगता है कि ऐसा करने का एक तरीका भी हो सकता है JOIN, लेकिन मैं इसके साथ नहीं आ सकता। मैं इसके साथ खेलता रहूंगा और अगर मुझे यह मिलता है तो मैं इसका जवाब दूंगा।

वैकल्पिक रूप से, @kaiser ने सुझाव दिया, आप इसे दो भागों में विभाजित कर सकते हैं: नेता प्राप्त करना और क्वेरी करना। मुझे लग रहा है कि यह कम कुशल हो सकता है, लेकिन यह निश्चित रूप से जाने के लिए अधिक समझने योग्य तरीका है। आपको अपने आप को निर्धारित करने के लिए दक्षता का परीक्षण करना होगा कि कौन सी विधि बेहतर है, क्योंकि नेस्टेड एसक्यूएल प्रश्न काफी धीमा हो सकता है।

टिप्पणियाँ से:

आपको फ़ंक्शन को अपने तरीके से रखना चाहिए functions.phpऔर कहा जाता है add_filter()की query()विधि से पहले सही करना चाहिए WP_Query। इसके तुरंत बाद, आपको remove_filter()ऐसा करना चाहिए ताकि यह अन्य प्रश्नों को प्रभावित न करे।


1
अपने ए को संपादित किया और जोड़ा prepare()। आशा है कि आप संपादन को ध्यान में नहीं रखेंगे। और हाँ: प्रदर्शन को ओपी द्वारा मापा जाना चाहिए। वैसे भी: मुझे अभी भी लगता है कि यह केवल usermeta होना चाहिए और कुछ नहीं।
कैसर

@ m0r7if3r एक समाधान की कोशिश करने के लिए Thx। मैंने सिर्फ कैसर के उत्तर के जवाब में एक टिप्पणी पोस्ट की, जिसमें संभावित स्केलेबिलिटी के मुद्दों पर चिंता व्यक्त की गई। कृपया इसे ध्यान में रखें।
जॉन

1
@kaiser कम से कम बुरा मत मानना, वास्तव में मैं इसकी सराहना करता हूं :)
mor7ifer

@ m0r7if3r धन्यवाद आप जैसे लोग सामुदायिक चट्टानों में हैं :)
kaiser

1
आपको फ़ंक्शन को अपने तरीके से रखना चाहिए functions.phpऔर कहा जाता है add_filter()की query()विधि से पहले सही करना चाहिए WP_Query। इसके तुरंत बाद, आपको remove_filter()ऐसा करना चाहिए ताकि यह अन्य प्रश्नों को प्रभावित न करे। मुझे यकीन नहीं है कि URL पुनर्लेखन में क्या समस्या होगी, मैंने posts_whereकई अवसरों पर उपयोग किया है और कभी नहीं देखा है ...
mor7ifer

6

टेम्प्लेट टैग

बस अपनी functions.phpफ़ाइल में दोनों फ़ंक्शन रखें । फिर 1 फ़ंक्शन को समायोजित करें और अपना कस्टम टेबल नाम जोड़ें। फिर आपको परिणामी सरणी के अंदर वर्तमान उपयोगकर्ता आईडी से छुटकारा पाने के लिए कुछ प्रयास / त्रुटि की आवश्यकता है (टिप्पणी देखें)।

/**
 * Get "Leaders" of the current user
 * @param int $user_id The current users ID
 * @return array $query The leaders
 */
function wpse50305_get_leaders( $user_id )
{
    global $wpdb;

    return $wpdb->query( $wpdb->prepare(
        "
            SELECT `leader_id`, `follower_id`
            FROM %s
                WHERE `follower_id` = %s
            ORDERBY `leader_id` ASC
        ",
        // Edit the table name
        "{$wpdb->prefix}custom_table_name"
        $user_id
    ) );
}

/**
 * Get posts array that contain posts by 
 * "Leaders" the current user is following
 * @return array $posts Posts that are by the current "Leader
 */
function wpse50305_list_posts_by_leader()
{
    get_currentuserinfo();
    global $current_user;

    $user_id = $current_user->ID;

    $leaders = wpse5035_get_leaders( $user_id );
    // could be that you need to loop over the $leaders
    // and get rid of the follower ids

    return get_posts( array(
        'author' => implode( ",", $leaders )
    ) );
}

टेम्पलेट के अंदर

यहां आप अपने परिणामों के साथ जो चाहें कर सकते हैं।

foreach ( wpse50305_list_posts_by_leader() as $post )
{
    // do something with $post
}

ध्यान दें, हमारे पास टेस्टाटा आदि नहीं हैं, इसलिए ऊपर एक अनुमान लगाने का थोड़ा सा खेल है। सुनिश्चित करें कि आप इस उत्तर को आपके लिए काम करने के साथ संपादित करते हैं, इसलिए हमारे पास बाद के पाठकों के लिए एक संतोषजनक परिणाम है। यदि आपने बहुत कम प्रतिनिधि प्राप्त किया है, तो मैं सम्पादन को स्वीकृत करूंगा। फिर आप इस नोट को हटा भी सकते हैं। धन्यवाद।


2
JOINहै और अधिक महंगा है। प्लस: जैसा कि मैंने उल्लेख किया है, हमारे पास परीक्षण डेटा नहीं है, इसलिए कृपया दोनों उत्तरों का परीक्षण करें और अपने परिणामों के साथ हमें बताएं।
कैसर

1
WP_Query ही क्वेरी करते समय पोस्ट टेबल और पोस्टमेटा के बीच जॉइन के साथ काम करता है। मैंने PHP मेमोरी यूज़ बम्प को 70MB - 200MB प्रति पेज लोड देखा है। कई एक साथ उपयोगकर्ताओं के साथ ऐसा कुछ चलाना एक चरम बुनियादी ढांचे की आवश्यकता होगी। मेरा अनुमान है कि चूंकि, वर्डप्रेस पहले से ही इसी तरह की तकनीक को लागू करता है, इसलिए आईडी की सरणी के साथ काम करने की तुलना में जॉयन्स को कम कर लगाना चाहिए।
जॉन

1
@ सुनकर अच्छा लगा। वास्तव में आगामी जानना चाहते हैं।
कैसर

4
ठीक है यहाँ परीक्षा परिणाम हैं। इसके लिए मैंने एक csv फ़ाइल से लगभग 47K उपयोगकर्ता जोड़े। बाद में, पहले 45 उपयोगकर्ताओं को हर दूसरे उपयोगकर्ता का पालन करने के लिए लूप के लिए दौड़ा। इसके परिणामस्वरूप मेरे कस्टम टेबल में 3,704,951 रिकॉर्ड बच गए। प्रारंभ में, @ m0r7if3r के समाधान ने मुझे 95 सेकंड का क्वेरी समय दिया, जो लीडर_आईडी कॉलम पर अनुक्रमण को चालू करने के बाद 0.020 एमएस पर चला गया। कुल PHP मेमोरी की खपत 20MB के आसपास थी। दूसरी ओर, आपके समाधान को अनुक्रमित करने के साथ क्वेरी के लिए लगभग 2 से 5 सेकंड लगते हैं। कुल PHP मेमोरी की खपत लगभग 117MB थी।
जॉन

1
मैं एक और उत्तर जोड़ता हूं (हम उस पर टिप्पणी में कोड स्वरूपण के रूप में उस पर प्रक्रिया कर सकते हैं / संशोधित कर सकते हैं): P
kaiser

3

नोट: यह उत्तर यहाँ टिप्पणियों में विस्तारित चर्चा से बचने के लिए है

  1. यहाँ परीक्षण उपयोगकर्ताओं के पहले सेट को जोड़ने के लिए टिप्पणियों से ओपी कोड है। मुझे एक वास्तविक दुनिया के उदाहरण में बदलना होगा।

    for ( $j = 2; $j <= 52; $j++ ) 
    {
        for ( $i = ($j + 1); $i <= 47000; $i++ )
        {
            $rows_affected = $wpdb->insert( $table_name, array( 'leader_id' => $i, 'follower_id' => $j ) );
        }
    }

    OP टेस्ट के बारे में इसके लिए मैंने एक csv फ़ाइल से लगभग 47K उपयोगकर्ता जोड़े। बाद में, पहले 45 उपयोगकर्ताओं को हर दूसरे उपयोगकर्ता का पालन करने के लिए लूप के लिए दौड़ा।

    • इसके परिणामस्वरूप मेरे कस्टम टेबल में 3,704,951 रिकॉर्ड बच गए।
    • प्रारंभ में, @ m0r7if3r के समाधान ने मुझे 95 सेकंड का क्वेरी समय दिया, जो लीडर_आईडी कॉलम पर अनुक्रमण को चालू करने के बाद 0.020 एमएस पर चला गया। कुल PHP मेमोरी की खपत 20MB के आसपास थी।
    • दूसरी ओर, आपके समाधान को अनुक्रमित करने के साथ क्वेरी के लिए लगभग 2 से 5 सेकंड लगते हैं। कुल PHP मेमोरी की खपत लगभग 117MB थी।
  2. इस: परीक्षण के लिए मेरा जवाब:

    अधिक "वास्तविक जीवन" परीक्षण: प्रत्येक उपयोगकर्ता का अनुसरण करें $leader_amount = rand( 0, 5 );और फिर $leader_amount x $random_ids = rand( 0, 47000 );प्रत्येक उपयोगकर्ता की संख्या जोड़ें । अब तक हम जो जानते हैं वह यह है: यदि कोई उपयोगकर्ता एक दूसरे उपयोगकर्ता का अनुसरण कर रहा है तो मेरा समाधान बहुत बुरा होगा। इसके अलावा: आप दिखाएँगे कि आपने परीक्षण कैसे किया और आपने टाइमर कहाँ जोड़ा है।

    मुझे यह भी बताना है कि समय ट्रैकिंग के ऊपर that वास्तव में मापा नहीं जा सकता है, क्योंकि यह एक साथ लूप की गणना करने के लिए समय भी लेगा। दूसरे लूप में आईडी के परिणामी सेट के माध्यम से लूप करना बेहतर होगा।

आगे की प्रक्रिया यहाँ


2
उन लोगों के लिए ध्यान दें जो इस प्रश्न का अनुसरण कर रहे हैं: मैं विभिन्न परिस्थितियों में प्रदर्शन को मापने की प्रक्रिया में हूं और एक या एक दिन में परिणाम पोस्ट करूंगा। परीक्षण डेटा के पैमाने के कारण यह अत्यंत समय लेने वाला कार्य रहा है जो कि होना चाहिए उत्पन्न।
जॉन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.