WP प्लगइन में क्लास शुरू करने का सबसे अच्छा तरीका है?


89

मैंने एक प्लगइन बनाया है, और निश्चित रूप से मेरे होने के नाते, मैं एक अच्छा ओओ दृष्टिकोण के साथ जाना चाहता था। अब मैं क्या कर रहा हूँ इस वर्ग को बनाने के लिए और फिर नीचे इस वर्ग का एक उदाहरण बनाएँ:

class ClassName {

    public function __construct(){

    }
}

$class_instance = new ClassName();  

मैं मान रहा हूं कि इस वर्ग को आरंभ करने के लिए एक अधिक WP तरीका है, और फिर मैं लोगों को यह कहते हुए आया कि वे एक init()से अधिक कार्य करना पसंद करते हैं __construct()। और इसी तरह मैंने कुछ लोगों को हुक का इस्तेमाल करते हुए पाया:

class ClassName {

    public function init(){

    }
}
add_action( 'load-plugins.php', array( 'ClassName', 'init' ) );

आमतौर पर लोड पर एक WP श्रेणी का उदाहरण बनाने के लिए सबसे अच्छा तरीका क्या माना जाता है और यह विश्व स्तर पर सुलभ चर के रूप में है?

नोट: एक दिलचस्प पक्ष बिंदु के रूप में, मैंने देखा है कि जबकि register_activation_hook()भीतर से बुलाया जा सकता है __construct, इसे init()दूसरे उदाहरण का उपयोग करने से नहीं बुलाया जा सकता है । शायद कोई मुझे इस बिंदु पर बता सके।

संपादित करें: सभी उत्तरों के लिए धन्यवाद, स्पष्ट रूप से बहस का एक सा हिस्सा है कि कक्षा के भीतर इनिशियलाइज़ेशन को कैसे हैंडल किया जाए, लेकिन मुझे लगता है कि आम तौर पर एक बहुत अच्छी आम सहमति है जो add_action( 'plugins_loaded', ...);वास्तव में इसे बंद करने का सबसे अच्छा तरीका है ...

संपादित करें: बस मामलों को भ्रमित करने के लिए, मैंने इसका उपयोग भी देखा है (हालांकि मैं इस पद्धति का उपयोग स्वयं नहीं करूंगा क्योंकि एक अच्छी तरह से ओओ वर्ग को एक समारोह में बदलना यह बात को हरा देता है):

// Start up this plugin
add_action( 'init', 'ClassName' );
function ClassName() {
    global $class_name;
    $class_name = new ClassName();
}

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

मैं थोड़े इस बात से सहमत हूं, लेकिन मुझे लगा कि जैसा मैंने WP प्लगइन्स के एक जोड़े में पाया था, वैसा ही रखा।
कल्पित

जवाबों:


60

अच्छा सवाल है, कई दृष्टिकोण हैं और यह इस बात पर निर्भर करता है कि आप क्या हासिल करना चाहते हैं।

मैं अक्सर करता हूं;

add_action( 'plugins_loaded', array( 'someClassy', 'init' ));

class someClassy {

    public static function init() {
        $class = __CLASS__;
        new $class;
    }

    public function __construct() {
           //construct what you see fit here...
    }

    //etc...
}

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

खाली कंस्ट्रक्टर दृष्टिकोण।

यहाँ ऊपर दिए गए गस्ट से लिए गए फायदे / नुकसान का एक अंश है जो पूर्ण रूप से खाली कंस्ट्रक्टर दृष्टिकोण की मिसाल देता है।

  • लाभ:

    • इकाई परीक्षण किसी भी हुक को स्वचालित रूप से सक्रिय किए बिना नए उदाहरण बना सकते हैं। कोई सिंगलटन नहीं।

    • कोई वैश्विक चर की जरूरत है।

    • जो कोई भी प्लगइन उदाहरण के साथ काम करना चाहता है, वह सिर्फ T5_Plugin_Class_Demo :: get_instance () कह सकता है।

    • निष्क्रिय करने के लिए आसान है।

    • अभी भी वास्तविक OOP: कोई भी कार्य विधि स्थिर नहीं है।

  • हानि:

    • शायद पढ़ने में कठिन हो?

मेरी राय में नुकसान उस पर एक कमजोर है, यही कारण है कि यह मेरा इष्ट दृष्टिकोण होगा, हालांकि केवल एक ही मैं उपयोग नहीं करता हूं। वास्तव में कई अन्य भारी भार इस विषय पर उनके विषय पर जल्द ही संदेह करने में कोई संदेह नहीं करेंगे क्योंकि इस विषय के आसपास कुछ अच्छे विचार हैं जिन्हें आवाज दी जानी चाहिए।


नोट: मुझे 3 या 4 की तुलना में चलाए जाने वाले जीचो से जिस्ट का उदाहरण ढूंढने की जरूरत है कि कैसे एक प्लगइन के भीतर एक क्लास को इंस्टेंट किया जाए जो प्रत्येक के पेशेवरों और विपक्षों को देखता था, जो उपरोक्त लिंक इसे करने का पसंदीदा तरीका था, लेकिन अन्य उदाहरण इस विषय के लिए एक अच्छा विपरीत प्रदान करते हैं। उम्मीद है कि toscho अभी भी है कि फाइल पर।

नोट: WPSE उत्तर प्रासंगिक उदाहरण और तुलना के साथ इस विषय के लिए। इसके अलावा वर्डप्रेस में एक वर्ग के लिए सबसे अच्छा समाधान।

add_shortcode( 'baztag', array( My_Plugin::get_instance(), 'foo' ) );
class My_Plugin {

    private $var = 'foo';

    protected static $instance = NULL;

    public static function get_instance() {

        // create an object
        NULL === self::$instance and self::$instance = new self;

        return self::$instance; // return the object
    }

    public function foo() {

        return $this->var; // never echo or print in a shortcode!
    }
}

add_action ('plugins_loaded', ...) के बीच क्या अंतर होगा; और add_action ('लोड- plugins.php', ...); उदाहरण मैंने बाद में लिया
कल्पा

1
लोड-प्लगइन्स.फैप को मैं जो समझता हूं, हालांकि यह काम करता है, कोर update.phpफाइल के साथ जुड़ा हुआ है और सामान्य डिफ़ॉल्ट क्रियाओं का हिस्सा नहीं है, जो कि उन घटनाओं पर अनुक्रम के विषय में निर्भर होने पर भरोसा किया जाना चाहिए जो प्रारंभ के दौरान आग लगाते हैं और इसी कारण से मैं पसंद करता हूं उन हुक का उपयोग करने के लिए जो इस मामले में लागू होते हैं plugins_loaded। यह वह है जो मैं अक्सर एक त्वरित स्नैपशॉट के रूप में संदर्भित करता हूं जब एक्शन संदर्भ होता है । मेरी व्याख्या अपनी संपूर्णता में पूरी नहीं है।
एडम

4
मुझे यह सिंगलटन जैसा दृष्टिकोण पसंद है। हालाँकि, मैं आपके शुरुआती कार्रवाई हुक के रूप में plugins_loaded का उपयोग करके सवाल करता हूं। यह हुक सभी प्लगइन्स लोड होने के बाद चलाने के लिए है । इसके बाद हुक करने से, आप उस हुक को हाईजैक कर रहे हैं, और अन्य प्लगइन्स या थीम के साथ टकराव या स्टार्टअप-सीक्वेंस के मुद्दों में मज़ा कर सकते हैं जो प्लग-इन में लोड होते हैं। मैं आपके इनिशियलाइज़ेशन मेथड को चलाने के लिए किसी भी एक्शन में नहीं जाऊँगा। प्लगइन आर्किटेक्चर को इनलाइन चलाने के लिए डिज़ाइन किया गया था, एक्शन पर नहीं।
टॉम ऑस्टर

2
ध्यान दें कि यदि आप उपयोग करते हैं register_activation_hook()तो plugins_loadedकार्रवाई शुरू होने से पहले आपको उस फ़ंक्शन को कॉल करना होगा ।
गीर्ट

1
अतिरिक्त जानकारी के रूप में, @mikeschinkel की इस पोस्ट और टिप्पणियों में dicuss देखें। hardcorewp.com/2012/…
बुलेटी

78

मूल प्रश्न पूछे जाने के ठीक 2 साल बाद यहां पहुंचना, कुछ बातें हैं जो मैं बताना चाहता हूं। (मुझे कभी बहुत सी बातें इंगित करने के लिए मत कहो)।

उचित हुक

प्लगइन क्लास को तुरंत करने के लिए, उचित हुक का उपयोग किया जाना चाहिए। एक सामान्य नियम नहीं है जिसके लिए यह है, क्योंकि यह इस बात पर निर्भर करता है कि वर्ग क्या करता है।

एक बहुत ही शुरुआती हुक का उपयोग करना जैसे "plugins_loaded"कोई मतलब नहीं है क्योंकि एक हुक ऐसा है जो व्यवस्थापक, फ़्रेन्ड और AJAX अनुरोधों के लिए निकाल दिया जाता है, लेकिन बहुत बार बाद में हुक बेहतर होता है क्योंकि यह केवल जरूरत पड़ने पर प्लगइन कक्षाओं को तुरंत करने की अनुमति देता है।

उदाहरण के लिए, सामानों के लिए सामान रखने वाली एक कक्षा को तुरंत चालू किया जा सकता है "template_redirect"

आम तौर पर यह बहुत कम ही कहा जाता है कि एक वर्ग को तुरंत "wp_loaded"निकाल दिया जाना चाहिए।

नो गॉड क्लास

पुराने जवाबों में उदाहरण के रूप में उपयोग की जाने वाली सभी कक्षाएं अधिकांश नाम की एक कक्षा का उपयोग करती हैं "Prefix_Example_Plugin"या "My_Plugin"... यह इंगित करता है कि शायद प्लगइन के लिए एक मुख्य वर्ग है।

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

ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग कोड में SOLID होना चाहिए, जहां "S" "सिंगल जिम्मेदारी सिद्धांत" के लिए खड़ा हो ।

इसका मतलब है कि हर वर्ग को एक ही काम करना चाहिए। वर्डप्रेस प्लगइन डेवलपमेंट में इसका मतलब है कि डेवलपर्स को मुख्य प्लगइन क्लास को इंस्टेंट करने के लिए सिंगल हुक का उपयोग करने से बचना चाहिए , लेकिन क्लास की जिम्मेदारी के अनुसार अलग-अलग हुक को अलग-अलग क्लास को इंस्टेंट करने के लिए इस्तेमाल किया जाना चाहिए।

कंस्ट्रक्टर में हुक से बचें

इस तर्क को अन्य उत्तरों में यहाँ प्रस्तुत किया गया है, हालाँकि मैं इस अवधारणा पर टिप्पणी करना चाहता हूँ और इस अन्य उत्तर को जोड़ना चाहता हूँ जहाँ इसे इकाई परीक्षण के दायरे में बहुत व्यापक रूप से समझाया गया है।

लगभग 2015: PHP 5.2 लाश के लिए है

14 अगस्त 2014 के बाद से, PHP 5.3 जीवन के अंत तक पहुंच गया । यह निश्चित रूप से मर चुका है। PHP 5.4 सभी 2015 के लिए समर्थित होने जा रहा है, इसका मतलब है कि मैं एक और वर्ष के लिए लिख रहा हूं।

हालाँकि, वर्डप्रेस अभी भी PHP 5.2 का समर्थन करता है, लेकिन किसी को भी उस संस्करण का समर्थन करने वाली कोड की एक पंक्ति नहीं लिखनी चाहिए, खासकर अगर कोड OOP है।

इसके अलग-अलग कारण हैं:

  • PHP 5.2 एक लंबे समय से पहले मर चुका है, इसके लिए कोई सुरक्षा सुधार जारी नहीं किए गए हैं, इसका मतलब है कि यह सुरक्षित नहीं है
  • PHP 5.3 में PHP, अनाम फ़ंक्शंस और नाम स्थान वाले सहयोगी के लिए बहुत सारी सुविधाएँ जोड़ी गईं
  • PHP के नए संस्करण बहुत तेज हैं । PHP मुफ्त है। इसे अपडेट करना मुफ्त है। यदि आप मुफ्त में तेज़, अधिक सुरक्षित उपयोग कर सकते हैं, तो एक धीमे, असुरक्षित संस्करण का उपयोग क्यों करें?

यदि आप PHP 5.4+ कोड का उपयोग नहीं करना चाहते हैं, तो कम से कम 5.3+ का उपयोग करें

उदाहरण

इस बिंदु पर यह पुराने समय की समीक्षा करने का समय है जो मैंने यहां तक ​​कहा था।

एक बार जब हमें 5.2 के बारे में परवाह नहीं करनी है, तो हम नाम स्थान का उपयोग कर सकते हैं और करना चाहिए।

एकल जिम्मेदारी सिद्धांत को बेहतर ढंग से समझाने के लिए, मेरा उदाहरण 3 वर्गों का उपयोग करेगा, एक जो फ्रंटएंड पर कुछ करता है , एक बैकएंड पर और तीसरा दोनों मामलों में उपयोग किया जाता है।

व्यवस्थापक वर्ग:

namespace GM\WPSE\Example;

class AdminStuff {

   private $tools;

   function __construct( ToolsInterface $tools ) {
     $this->tools = $tools;
   }

   function setup() {
      // setup class, maybe add hooks
   }

}

सीमावर्ती वर्ग:

namespace GM\WPSE\Example;

class FrontStuff {

   private $tools;

   function __construct( ToolsInterface $tools ) {
     $this->tools = $tools;
   }

   function setup() {
      // setup class, maybe add hooks
   }

}

उपकरण इंटरफ़ेस:

namespace GM\WPSE\Example;

interface ToolsInterface {

   function doSomething();

}

और एक उपकरण वर्ग, अन्य दो द्वारा उपयोग किया जाता है:

namespace GM\WPSE\Example;

class Tools implements ToolsInterface {

   function doSomething() {
      return 'done';
   }

}

इस कक्षाएं होने के बाद, मैं उचित हुक का उपयोग करके उन्हें इंस्टेंट कर सकता हूं। कुछ इस तरह:

require_once plugin_dir_path( __FILE__ ) . 'src/ToolsInterface.php';
require_once plugin_dir_path( __FILE__ ) . 'src/Tools.php';

add_action( 'admin_init', function() {

   require_once plugin_dir_path( __FILE__ ) . 'src/AdminStuff.php';
   $tools = new GM\WPSE\Example\Tools;
   global $admin_stuff; // this is not ideal, reason is explained below
   $admin_stuff = new GM\WPSE\Example\AdminStuff( $tools ); 
} );

add_action( 'template_redirect', function() {

   require_once plugin_dir_path( __FILE__ ) . 'src/FrontStuff.php';
   $tools = new GM\WPSE\Example\Tools;
   global $front_stuff; // this is not ideal, reason is explained below
   $front_stuff = new GM\WPSE\Example\FrontStuff( $tools );    
} );

निर्भरता उलटा और निर्भरता इंजेक्शन

ऊपर दिए गए उदाहरण में मैंने अलग-अलग हुक में अलग-अलग वर्गों को तुरंत लिखने के लिए नाम स्थान और अनाम कार्यों का उपयोग किया, जो मैंने ऊपर कहा था, अभ्यास में डाल दिया।

ध्यान दें कि कैसे नामस्थान बिना किसी उपसर्ग के नाम वाली कक्षाएं बनाने की अनुमति देते हैं।

मैंने एक और अवधारणा लागू की जिसका परोक्ष रूप से ऊपर उल्लेख किया गया था: डिपेंडेंसी इंजेक्शन , यह एक तरीका है कि डिपेंडेंसी इनवर्जन प्रिंसिपल , "डी" को SOLID के ब्रीफकेस में लागू किया जाए ।

Toolsवर्ग "इंजेक्शन" है अन्य दो वर्गों में जब वे instantiated कर रहे हैं, तो इस तरह से यह जिम्मेदारी अलग करने के लिए संभव है।

इसके अलावा, AdminStuffऔर FrontStuffकक्षाएं यह बताने के लिए कि वे एक वर्ग की जरूरत को लागू करने के लिए टाइप हिंटिंग का उपयोग करती हैं ToolsInterface

इस तरह से स्वयं या हमारे कोड का उपयोग करने वाले उपयोगकर्ता एक ही इंटरफ़ेस के विभिन्न कार्यान्वयन का उपयोग कर सकते हैं, जिससे हमारा कोड एक ठोस वर्ग के लिए नहीं बल्कि एक अमूर्त के लिए युग्मित हो जाता है: यह वास्तव में डिपेंडेंसी इनवर्जन सिद्धांत के बारे में है।

हालाँकि, ऊपर दिए गए उदाहरण में और सुधार किया जा सकता है। आइए देखें कैसे।

autoloader

बेहतर पठनीय ओओपी कोड लिखने का एक अच्छा तरीका अन्य कोड के साथ प्रकार (इंटरफेसेस, क्लासेस) की परिभाषा को मिक्स करना नहीं है , और हर प्रकार की अपनी फ़ाइल में डालना है।

यह नियम PSR-1 कोडिंग मानकों 1 में से एक भी है

हालाँकि, ऐसा करने से पहले, एक वर्ग का उपयोग करने में सक्षम होने के लिए उस फ़ाइल की आवश्यकता होती है जिसमें यह होता है।

यह भारी हो सकता है, लेकिन PHP एक कॉलबैक का उपयोग करके एक वर्ग को ऑटो लोड करने के लिए उपयोगिता फ़ंक्शन प्रदान करता है, जो कि उसके नाम के आधार पर एक फ़ाइल लोड करता है।

नेमस्पेस का उपयोग करना बहुत आसान हो जाता है, क्योंकि अब नाम संरचना के साथ फ़ोल्डर संरचना से मेल खाना संभव है।

यह न केवल संभव है, बल्कि यह एक और PSR मानक (या बेहतर 2: PSR-0 अब पदावनत, और PSR-4 ) है।

उस मानकों का पालन करते हुए विभिन्न उपकरणों का उपयोग करना संभव है जो एक कस्टम ऑटोलॉडेर को कोड किए बिना, ऑटोलैड को संभालते हैं।

मेरा कहना है कि वर्डप्रेस कोडिंग मानकों में फाइलों के नामकरण के लिए अलग नियम हैं।

इसलिए वर्डप्रेस कोर के लिए कोड लिखते समय, डेवलपर्स को WP नियमों का पालन करना होता है, लेकिन कस्टम कोड लिखते समय यह एक डेवलपर विकल्प होता है, लेकिन PSR मानक का उपयोग करना पहले से ही लिखित टूल 2 का उपयोग करना आसान होता है ।

ग्लोबल एक्सेस, रजिस्ट्री और सर्विस लोकेटर पैटर्न।

वर्डप्रेस में प्लगइन कक्षाओं को तत्काल करते समय सबसे बड़े मुद्दों में से एक, कोड के विभिन्न हिस्सों से उन्हें कैसे एक्सेस किया जाए।

वर्डप्रेस स्वयं वैश्विक दृष्टिकोण का उपयोग करता है : चर वैश्विक दायरे में सहेजे जाते हैं, जिससे वे हर जगह सुलभ हो जाते हैं। प्रत्येक WP डेवलपर globalअपने करियर में हजारों बार शब्द टाइप करता है ।

यह भी दृष्टिकोण है जिसका मैंने ऊपर उदाहरण के लिए उपयोग किया है, लेकिन यह बुराई है

यह उत्तर पहले से ही मुझे समझाने की अनुमति देने के लिए बहुत लंबा है, लेकिन "वैश्विक चर बुराई" के लिए SERP में पहला परिणाम पढ़ना एक अच्छा प्रारंभिक बिंदु है।

लेकिन वैश्विक चर से बचना कैसे संभव है?

भिन्न भिन्न तरीका होता है।

यहाँ कुछ पुराने उत्तर स्थैतिक उदाहरण दृष्टिकोण का उपयोग करते हैं ।

public static function instance() {

  if ( is_null( self::$instance ) ) {
    self::$instance = new self;
  }

  return self::$instance;
}

यह आसान और बहुत अच्छा है, लेकिन यह हर उस वर्ग के पैटर्न को लागू करने के लिए मजबूर करता है जिसे हम एक्सेस करना चाहते हैं।

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

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

इसका मतलब यह नहीं है कि इसका उपयोग केवल कुछ ही वर्गों वाले प्लगइन्स के लिए किया जा सकता है, वास्तव में, जब निर्भरता इंजेक्शन सिद्धांत का ठीक से उपयोग किया जाता है, तो विश्व स्तर पर बड़ी संख्या में पहुंच बनाने की आवश्यकता के बिना सुंदर जटिल एप्लिकेशन बनाना संभव है। वस्तुओं की।

हालांकि, कभी-कभी प्लगइन्स को कुछ वर्गों तक पहुंच बनाने की आवश्यकता होती है, और उस स्थिति में स्थिर उदाहरण दृष्टिकोण भारी होता है।

रजिस्ट्री पैटर्न का उपयोग करने के लिए एक और संभावित दृष्टिकोण है ।

यह इसका एक बहुत ही सरल कार्यान्वयन है:

namespace GM\WPSE\Example;

class Registry {

   private $storage = array();

   function add( $id, $class ) {
     $this->storage[$id] = $class;
   }

   function get( $id ) {
      return array_key_exists( $id, $this->storage ) ? $this->storage[$id] : NULL;
   }

}

इस कक्षा का उपयोग करके एक आईडी द्वारा रजिस्ट्री ऑब्जेक्ट में वस्तुओं को संग्रहीत करना संभव है, इसलिए एक रजिस्ट्री तक पहुंच होने से सभी वस्तुओं तक पहुंच संभव है। बेशक जब कोई वस्तु पहली बार बनाई जाती है तो उसे रजिस्ट्री में जोड़ा जाना चाहिए।

उदाहरण:

global $registry;

if ( is_null( $registry->get( 'tools' ) ) ) {
  $tools = new GM\WPSE\Example\Tools;
  $registry->add( 'tools', $tools );
}

if ( is_null( $registry->get( 'front' ) ) ) {
  $front_stuff = new GM\WPSE\Example\FrontStuff( $registry->get( 'tools' ) );    
  $registry->add( 'front', front_stuff );
}

add_action( 'wp', array( $registry->get( 'front' ), 'wp' ) );

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

function gm_wpse_example_registry() {
  static $registry = NULL;
  if ( is_null( $registry ) ) {
    $registry = new GM\WPSE\Example\Registry;
  }
  return $registry;
}

पहली बार फ़ंक्शन को यह कहा जाता है कि यह रजिस्ट्री को तुरंत रद्द कर देगा, बाद की कॉल पर यह इसे वापस कर देगा।

विश्व स्तर पर सुलभ बनाने के लिए एक और वर्डप्रेस-विशिष्ट विधि एक फिल्टर से एक वस्तु उदाहरण लौटा रही है। कुछ इस तरह:

$registry = new GM\WPSE\Example\Registry;

add_filter( 'gm_wpse_example_registry', function() use( $registry ) {
  return $registry;
} );

उसके बाद हर जगह रजिस्ट्री की जरूरत है:

$registry = apply_filters( 'gm_wpse_example_registry', NULL );

एक और पैटर्न जिसका उपयोग किया जा सकता है वह है सेवा लोकेटर पैटर्न । यह रजिस्ट्री पैटर्न के समान है, लेकिन सर्विस लोकेटरों को निर्भरता इंजेक्शन का उपयोग करके विभिन्न वर्गों में पास किया जाता है।

इस पैटर्न के साथ मुख्य समस्या यह है कि यह कक्षाओं की निर्भरता को छुपाता है जिससे कोड को बनाए रखने और पढ़ने में मुश्किल होती है।

डि कंटेनर

कोई फर्क नहीं पड़ता कि रजिस्ट्री या सेवा लोकेटर का उपयोग विश्व स्तर पर सुलभ बनाने के लिए किया जाता है, वस्तुओं को वहां संग्रहीत किया जाना चाहिए, और संग्रहीत किए जाने से पहले उन्हें तत्काल करने की आवश्यकता है।

जटिल अनुप्रयोगों में, जहां बहुत अधिक कक्षाएं हैं और उनमें से कई में कई निर्भरताएं हैं, तात्कालिक कक्षाओं के लिए बहुत अधिक कोड की आवश्यकता होती है, इसलिए बग की संभावना बढ़ जाती है: कोड जो मौजूद नहीं है उसमें बग नहीं हो सकते।

पिछले वर्षों में कुछ PHP लाइब्रेरीज़ दिखाई दीं जो PHP डेवलपर्स को ऑब्जेक्ट्स के इंस्टेंस को आसानी से इंस्टेंट और स्टोर करने में मदद करती हैं, स्वचालित रूप से उनकी निर्भरता को हल करती हैं।

इस लाइब्रेरी को डिपेंडेंसी इंजेक्शन कंटेनरों के रूप में जाना जाता है क्योंकि वे निर्भरता को हल करने वाली कक्षाओं को इंस्टेंट करने में सक्षम हैं और वस्तुओं को स्टोर करने और जरूरत पड़ने पर उन्हें वापस करने के लिए भी, एक रजिस्ट्री ऑब्जेक्ट के समान कार्य करते हैं।

आमतौर पर, जब डीआई कंटेनरों का उपयोग करते हैं, तो डेवलपर्स को आवेदन के हर वर्ग के लिए निर्भरताएं निर्धारित करनी होती हैं, और फिर कोड में पहली बार एक वर्ग की आवश्यकता होती है जिसे उचित निर्भरता के साथ त्वरित किया जाता है और उसी उदाहरण को बाद के अनुरोधों पर फिर से लौटाया जाता है। ।

कुछ DI कंटेनर कॉन्फ़िगरेशन के बिना स्वचालित रूप से निर्भरता की खोज करने में सक्षम हैं, लेकिन PHP प्रतिबिंब का उपयोग कर रहे हैं ।

कुछ जाने माने DI कंटेनर हैं:

और बहुत सारे।

मैं यह बताना चाहता हूं कि सरल प्लगइन्स के लिए, जिसमें केवल कुछ वर्गों और वर्गों की बहुत अधिक निर्भरता नहीं है, शायद यह DI कंटेनरों का उपयोग करने के लायक नहीं है: स्थिर इंस्टेंस विधि या एक वैश्विक सुलभ रजिस्ट्री अच्छे समाधान हैं, लेकिन जटिल प्लगइन्स के लिए DI कंटेनर का लाभ स्पष्ट हो जाता है।

बेशक, यहां तक ​​कि डीआई कंटेनर ऑब्जेक्ट्स को एप्लिकेशन में उपयोग करने के लिए सुलभ होना पड़ता है और इस उद्देश्य के लिए उपरोक्त तरीकों में से किसी एक का उपयोग करना संभव है, वैश्विक चर, स्थिर उदाहरण चर, फ़िल्टर के माध्यम से वस्तु वापस करना और इसी तरह।

संगीतकार

DI कंटेनर का उपयोग करने का मतलब अक्सर 3 पार्टी कोड का उपयोग करना होता है। आजकल, PHP में, जब हमें एक बाहरी lib (इसलिए केवल DI कंटेनरों का उपयोग करने की आवश्यकता नहीं होती है, लेकिन कोई भी कोड जो एप्लिकेशन का हिस्सा नहीं है), बस इसे डाउनलोड करना और इसे हमारे एप्लिकेशन फ़ोल्डर में रखना एक अच्छा अभ्यास नहीं माना जाता है। भले ही हम कोड के उस अन्य टुकड़े के लेखक हैं।

बाहरी निर्भरता से एक आवेदन कोड को कम करना बेहतर संगठन, बेहतर विश्वसनीयता और कोड की बेहतर पवित्रता का संकेत है ।

संगीतकार , PHP निर्भरता का प्रबंधन करने के लिए PHP समुदाय में डी-फैक्टो मानक है। WP समुदाय में मुख्य धारा से दूर होना , यह एक ऐसा उपकरण है जिसे हर PHP और वर्डप्रेस डेवलपर को कम से कम जानना चाहिए, यदि उपयोग नहीं किया गया है।

यह उत्तर पहले से ही पुस्तक-आकार है जो आगे की चर्चा की अनुमति देता है, और यहां कम्पोजर पर चर्चा करना भी शायद विषय से दूर है, यह केवल पूर्णता के लिए उल्लेख किया गया था।

अधिक जानकारी के लिए संगीतकार साइट पर जाएँ और यह भी इस को पढ़ने देने के लायक है minisite द्वारा क्यूरेट @Rarst


1 PSR PHP फ्रेमवर्क इंटरॉप ग्रुप द्वारा जारी PHP मानक नियम हैं

2 संगीतकार (एक पुस्तकालय जिसका इस उत्तर में उल्लेख किया जाएगा) अन्य बातों के अलावा एक ऑटोलैडर उपयोगिता भी है।


1
एक अतिरिक्त नोट, कि PHP 5.3 भी जीवन का अंत है। एक जिम्मेदार होस्ट कम से कम 5.4 को एक विकल्प के रूप में पेश करेगा यदि कोई डिफ़ॉल्ट नहीं है
टॉम जे नोवेल

2
"14 अगस्त 2014 के बाद से, PHP 5.3 जीवन के अंत तक पहुँच गया। यह निश्चित रूप से मृत है।" के तहत पहली पंक्ति है "पीएचपी 5.2 लाश के लिए है" @TomJNowell
gmazzap

3
बस सोच रहा था, आप "बहुत सी चीजों" की तरह क्या इशारा करेंगे ? ;-)
माइकस्किंकेल

वैश्विक चर से बचने के प्रयासों में, मुझे फ़ंक्शन और स्थिर चर के साथ रजिस्ट्री पैटर्न का विचार पसंद है। पहली बार फ़ंक्शन को यह कहा जाता है कि यह रजिस्ट्री को तुरंत रद्द कर देगा, बाद की कॉल पर यह इसे वापस कर देगा।
माइकल Ecklund

10

मैं निम्नलिखित संरचना का उपयोग करता हूं:

Prefix_Example_Plugin::on_load();

/**
 * Example of initial class-based plugin load.
 */
class Prefix_Example_Plugin {

    /**
     * Hooks init (nothing else) and calls things that need to run right away.
     */
    static function on_load() {

        // if needed kill switch goes here (if disable constant defined then return)

        add_action( 'init', array( __CLASS__, 'init' ) );
    }

    /**
     * Further hooks setup, loading files, etc.
     *
     * Note that for hooked methods name equals hook (when possible).
     */
    static function init(  ) {


    }
}

टिप्पणियाँ:

  • उन चीजों के लिए जगह निर्धारित की गई है जिन्हें तुरंत चलाने की आवश्यकता है
  • विकलांगों के लिए अक्षम / ओवरराइड करना आसान है (एक initविधि को अनहुक करें )
  • मुझे नहीं लगता कि मैंने कभी भी प्लगइन क्लास का उपयोग किया / आवश्यक वस्तु - इसके बारे में जानकारी रखने की आवश्यकता है, आदि; यह वास्तव में नकली नामस्थान है, ओओपी (ज्यादातर समय)

अस्वीकरण मैं अभी तक यूनिट परीक्षणों का उपयोग नहीं करता ( myplate पर बहुत सारी चीजें ) और मैंने सुना है कि स्थैतिक उनके लिए कम बेहतर हो सकता है। इस पर अपना शोध करें यदि आपको इसकी जांच करने की आवश्यकता है।


3
मुझे पता है कि यूनिट टेस्टिंग में बड़े लोग वास्तव में स्टैटिक / सिंगलटन समाधान पसंद नहीं करते हैं। मुझे लगता है कि यदि आप पूरी तरह से समझते हैं कि आप स्थैतिक का उपयोग करके क्या हासिल करने का प्रयास कर रहे हैं और कम से कम ऐसा करने के प्रभाव के बारे में जानते हैं तो ऐसे तरीकों को लागू करने के लिए पूरी तरह से ठीक है। स्टैक ओवरफ्लो
एडम

इसने मुझे वास्तव में सोचने पर मजबूर कर दिया। तो क्यों एक वर्ग का उपयोग करें और न केवल सरल उपसर्ग कार्यों पर वापस जाएं। क्या हम ऐसा सिर्फ क्लीनर फंक्शन / मेथड नेम के लिए करते हैं? मेरा मतलब है कि उन्हें "स्थिर" बी 4 के साथ नेस्टेड किया गया है, क्या यह इतना अधिक पठनीय है? नाम संघर्ष होने की संभावना एक एकल वर्ग के नाम के समान है यदि आप प्रॉपर उपसर्ग का उपयोग करते हैं या मैं कुछ याद कर रहा हूं?
जेम्स मिच

1
@JamesMitch हाँ, सभी-स्टैटिक विधियाँ ज्यादातर नकली नेमस्पेस के साथ काम करती हैं जैसा कि WP में इस्तेमाल किया गया है। हालाँकि इस मामले में कक्षाओं का कुछ फ़ायदा शुद्ध कार्यों पर भी होता है, जैसे कि ऑटोलॉड और विरासत। हाल ही में मैं स्थैतिक तरीकों से आगे बढ़ रहा हूं और निर्भरता इंजेक्शन कंटेनर द्वारा आयोजित वास्तविक तात्कालिक वस्तुओं की ओर।
रारस्ट

3

यह सब कार्यक्षमता पर निर्भर करता है।

मैंने एक बार एक प्लगइन बनाया था जो स्क्रिप्ट को पंजीकृत करता था जब निर्माता को बुलाया जाता था इसलिए मुझे इसे हुक पर हुक करना पड़ता था wp_enqueue_scripts

यदि आप अपनी functions.phpफ़ाइल लोड होने पर उसे कॉल करना चाहते हैं , तो आप स्वयं एक उदाहरण बना सकते हैं जैसा $class_instance = new ClassName();कि आपने उल्लेख किया है।

आप गति और स्मृति उपयोग पर विचार करना चाह सकते हैं। मुझे किसी की जानकारी नहीं है, लेकिन मैं सोच सकता हूं कि कुछ मामलों में अनकवर्ड हुक हैं। उस हुक पर अपना उदाहरण बनाकर आप कुछ सर्वर संसाधनों को बचा सकते हैं।


उसके लिए कूल थैंक्स, मुझे लगता है कि उपरोक्त प्रश्न के भी दो अंक हैं। अन्य __construct उपयुक्त है या क्या init () वर्ग को इनिशियलाइज़ करने का एक बेहतर तरीका है।
kalpaitch

1
ठीक है, मैं एक स्थिर init()विधि के लिए जाऊंगा ताकि क्लास का उदाहरण एक और स्कोप के बजाय क्लास के स्कोप में बुलाया जाए जहां आप संभवतः मौजूदा वैरिएबल को ओवरराइट कर सकते हैं।
टिम एस।

0

मुझे पता है कि यह कुछ साल पुराना है, लेकिन इस बीच php 5.3 गुमनाम तरीकों का समर्थन करता है , इसलिए मैं इसके साथ आया:

add_action( 'plugins_loaded', function() { new My_Plugin(); } );

और किसी तरह मैं इसे सबसे ज्यादा पसंद करता हूं। मैं नियमित निर्माणकर्ताओं का उपयोग कर सकता हूं और मेरे ओओपी संरचनाओं को गड़बड़ाने वाले किसी भी "इनिट" या "ऑन_लोड" तरीकों को परिभाषित करने की आवश्यकता नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.