एक PHP आवेदन के लिए प्लग-इन की अनुमति के लिए सबसे अच्छा तरीका है

वोट
245

मैं PHP में एक नया वेब अनुप्रयोग और इस बार शुरू करने कर रहा हूँ चारों ओर मैं कुछ है कि लोगों को एक प्लगइन इंटरफ़ेस का उपयोग करके विस्तार कर सकते हैं बनाना चाहते हैं।

अपने कोड में 'हुक' लिख ताकि प्लगइन्स विशिष्ट घटनाओं के लिए संलग्न कर सकते हैं के बारे में कैसे जाता है?

01/08/2008 को 11:50
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


8 जवाब

वोट
14

मेरा मानना ​​है कि सबसे आसान तरीका है जेफ की अपनी सलाह का पालन करें और मौजूदा कोड के आसपास देखने के लिए होगा। WordPress, Drupal, जूमला और कम से देखने का प्रयास करें अन्य अच्छी तरह से ज्ञात पीएचपी आधारित सीएमएस अपने एपीआई हुक देखो और महसूस कैसे को देखने के लिए। इस तरह आप भी विचारों आपने पहले नहीं सोचा हो सकता है चीजों को थोड़ा और rubust बनाने के लिए मिल सकता है।

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

01/08/2008 को 12:44
का स्रोत उपयोगकर्ता

वोट
148

आप एक पर्यवेक्षक पैटर्न का उपयोग कर सकते हैं। एक साधारण कार्यात्मक तरीका यह है:

<?php

/** Plugin system **/

$listeners = array();

/* Create an entry point for plugins */
function hook() {
    global $listeners;

    $num_args = func_num_args();
    $args = func_get_args();

    if($num_args < 2)
        trigger_error("Insufficient arguments", E_USER_ERROR);

    // Hook name should always be first argument
    $hook_name = array_shift($args);

    if(!isset($listeners[$hook_name]))
        return; // No plugins have registered this hook

    foreach($listeners[$hook_name] as $func) {
        $args = $func($args); 
    }
    return $args;
}

/* Attach a function to a hook */
function add_listener($hook, $function_name) {
    global $listeners;
    $listeners[$hook][] = $function_name;
}

/////////////////////////

/** Sample Plugin **/
add_listener('a_b', 'my_plugin_func1');
add_listener('str', 'my_plugin_func2');

function my_plugin_func1($args) {
    return array(4, 5);
}

function my_plugin_func2($args) {
    return str_replace('sample', 'CRAZY', $args[0]);
}

/////////////////////////

/** Sample Application **/

$a = 1;
$b = 2;

list($a, $b) = hook('a_b', $a, $b);

$str  = "This is my sample application\n";
$str .= "$a + $b = ".($a+$b)."\n";
$str .= "$a * $b = ".($a*$b)."\n";

$str = hook('str', $str);
echo $str;
?>

आउटपुट:

This is my CRAZY application
4 + 5 = 9
4 * 5 = 20

टिप्पणियाँ:

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

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

क्षमा करें, यह प्रतीत होता है अंडरस्कोर वर्ण Markdown द्वारा HTML निकाय द्वारा प्रतिस्थापित कर रहे हैं? मैं इस कोड को फिर से पोस्ट कर सकते हैं जब इस बग तय हो जाता है।

संपादित करें: कोई बात नहीं, यह केवल कि जिस तरह से प्रकट होता है जब आप संपादन कर रहे

01/08/2008 को 12:46
का स्रोत उपयोगकर्ता

वोट
31

हुक और श्रोता विधि सबसे अधिक इस्तेमाल किया है, लेकिन वहाँ अन्य बातों के आप कर सकते हैं। अपने अनुप्रयोग के आकार पर निर्भर करता है, और अपने कोड को देखने की अनुमति देने के लिए जा रहा है जो बहुत प्रभावित करती है आप कैसे प्लगइन्स अनुमति देना चाहते हैं (यह एक FOSS स्क्रिप्ट, या घर में कुछ होने जा रहा है)।

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

+1 मुझ से kdeloach करने के लिए।

01/08/2008 को 16:23
का स्रोत उपयोगकर्ता

वोट
13

वहाँ एक स्वच्छ परियोजना कहा जाता है एक प्रकार की छोटी है कि PHP में प्लग-इन से निपटने के लिए काम का ज्यादा संभालती याहू पर मैट Zandstra द्वारा।

यह लागू करता है एक प्लगइन वर्ग के इंटरफेस, एक कमांड लाइन इंटरफेस का समर्थन करता है और भी उठना कठिन है और चल रहा नहीं है - खासकर यदि आप इसके बारे में कवर स्टोरी पढ़ पीएचपी वास्तुकार पत्रिका

17/09/2008 को 18:00
का स्रोत उपयोगकर्ता

वोट
10

अच्छी सलाह है कि यह कैसे अन्य परियोजनाओं किया है देखने के लिए है। प्लग इन इंस्टॉल और उनके "नाम" होने के लिए कई कॉल सेवाओं के लिए पंजीकृत (जैसे वर्डप्रेस करता है) ताकि आप "अंक" अपने कोड में जहाँ आप एक समारोह है कि पंजीकृत श्रोताओं को पहचान कर उनमें कार्यान्वित फोन है। एक मानक OO डिजाइन गपशप है ऑब्जर्वर पैटर्न है, जो वास्तव में एक उन्मुख वस्तु पीएचपी प्रणाली में लागू करने के लिए एक अच्छा विकल्प होगा।

Zend फ्रेमवर्क कई hooking तरीकों का उपयोग करता है, और बहुत अच्छी तरह से architected है। यह एक अच्छी प्रणाली को देखने के लिए होगा।

17/09/2008 को 18:38
का स्रोत उपयोगकर्ता

वोट
19

यहाँ एक दृष्टिकोण मैं का उपयोग किया है है, यह पर्यवेक्षक पैटर्न का एक प्रकार क्यूटी संकेत / स्लॉट तंत्र से नकल करने की कोशिश, है। वस्तुओं संकेतों फेंकना कर सकते हैं। हर संकेत प्रणाली में एक आईडी है - यह उन्हें प्राप्त जब कुछ प्रेषक का आईडी + ऑब्जेक्ट नाम हर संकेत रिसीवर, जो केवल एक "प्रतिदेय" तुम एक बस वर्ग किसी को संकेतों में रुचि पारित करने के लिए उपयोग करें से आबद्ध किया जा सकता है द्वारा रचित है क्या होता है, तो आप एक संकेत "भेजें"। नीचे और उदाहरण दिया गया है

    <?php

class SignalsHandler {


    /**
     * hash of senders/signals to slots
     *
     * @var array
     */
    private static $connections = array();


    /**
     * current sender
     *
     * @var class|object
     */
    private static $sender;


    /**
     * connects an object/signal with a slot
     *
     * @param class|object $sender
     * @param string $signal
     * @param callable $slot
     */
    public static function connect($sender, $signal, $slot) {
        if (is_object($sender)) {
            self::$connections[spl_object_hash($sender)][$signal][] = $slot;
        }
        else {
            self::$connections[md5($sender)][$signal][] = $slot;
        }
    }


    /**
     * sends a signal, so all connected slots are called
     *
     * @param class|object $sender
     * @param string $signal
     * @param array $params
     */
    public static function signal($sender, $signal, $params = array()) {
        self::$sender = $sender;
        if (is_object($sender)) {
            if ( ! isset(self::$connections[spl_object_hash($sender)][$signal])) {
                return;
            }
            foreach (self::$connections[spl_object_hash($sender)][$signal] as $slot) {
                call_user_func_array($slot, (array)$params);
            }

        }
        else {
            if ( ! isset(self::$connections[md5($sender)][$signal])) {
                return;
            }
            foreach (self::$connections[md5($sender)][$signal] as $slot) {
                call_user_func_array($slot, (array)$params);
            }
        }

        self::$sender = null;
    }


    /**
     * returns a current signal sender
     *
     * @return class|object
     */
    public static function sender() {
        return self::$sender;
    }

}   

class User {

    public function login() {
        /**
         * try to login
         */
        if ( ! $logged ) {
            SignalsHandler::signal(this, 'loginFailed', 'login failed - username not valid' );
        }
    }

}

class App {
    public static function onFailedLogin($message) {
        print $message;
    }
}


$user = new User();
SignalsHandler::connect($user, 'loginFailed', array($Log, 'writeLog'));
SignalsHandler::connect($user, 'loginFailed', array('App', 'onFailedLogin'));

$user->login();

?>
25/09/2008 को 20:29
का स्रोत उपयोगकर्ता

वोट
51

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

<?php

////////////////////
// PART 1
////////////////////

class Plugin {

    private $_RefObject;
    private $_Class = '';

    public function __construct(&$RefObject) {
        $this->_Class = get_class(&$RefObject);
        $this->_RefObject = $RefObject;
    }

    public function __set($sProperty,$mixed) {
        $sPlugin = $this->_Class . '_' . $sProperty . '_setEvent';
        if (is_callable($sPlugin)) {
            $mixed = call_user_func_array($sPlugin, $mixed);
        }   
        $this->_RefObject->$sProperty = $mixed;
    }

    public function __get($sProperty) {
        $asItems = (array) $this->_RefObject;
        $mixed = $asItems[$sProperty];
        $sPlugin = $this->_Class . '_' . $sProperty . '_getEvent';
        if (is_callable($sPlugin)) {
            $mixed = call_user_func_array($sPlugin, $mixed);
        }   
        return $mixed;
    }

    public function __call($sMethod,$mixed) {
        $sPlugin = $this->_Class . '_' .  $sMethod . '_beforeEvent';
        if (is_callable($sPlugin)) {
            $mixed = call_user_func_array($sPlugin, $mixed);
        }
        if ($mixed != 'BLOCK_EVENT') {
            call_user_func_array(array(&$this->_RefObject, $sMethod), $mixed);
            $sPlugin = $this->_Class . '_' . $sMethod . '_afterEvent';
            if (is_callable($sPlugin)) {
                call_user_func_array($sPlugin, $mixed);
            }       
        } 
    }

} //end class Plugin

class Pluggable extends Plugin {
} //end class Pluggable

////////////////////
// PART 2
////////////////////

class Dog {

    public $Name = '';

    public function bark(&$sHow) {
        echo "$sHow<br />\n";
    }

    public function sayName() {
        echo "<br />\nMy Name is: " . $this->Name . "<br />\n";
    }


} //end class Dog

$Dog = new Dog();

////////////////////
// PART 3
////////////////////

$PDog = new Pluggable($Dog);

function Dog_bark_beforeEvent(&$mixed) {
    $mixed = 'Woof'; // Override saying 'meow' with 'Woof'
    //$mixed = 'BLOCK_EVENT'; // if you want to block the event
    return $mixed;
}

function Dog_bark_afterEvent(&$mixed) {
    echo $mixed; // show the override
}

function Dog_Name_setEvent(&$mixed) {
    $mixed = 'Coco'; // override 'Fido' with 'Coco'
    return $mixed;
}

function Dog_Name_getEvent(&$mixed) {
    $mixed = 'Different'; // override 'Coco' with 'Different'
    return $mixed;
}

////////////////////
// PART 4
////////////////////

$PDog->Name = 'Fido';
$PDog->Bark('meow');
$PDog->SayName();
echo 'My New Name is: ' . $PDog->Name;

भाग 1 में, कि क्या आप एक साथ शामिल हो सकता है है require_once()अपने PHP स्क्रिप्ट के शीर्ष पर कॉल। यह कुछ प्लगेबल बनाने के लिए कक्षाओं में लोड करता है।

भाग 2 में, कि जहां हम एक वर्ग लोड है। नोट मैं कुछ भी वर्ग है, जो पर्यवेक्षक पैटर्न की तुलना में काफी अलग है के लिए विशेष करने की जरूरत नहीं है।

भाग 3 में, कि हम कहाँ जा रहा है "प्लगेबल" में भर में हमारे वर्ग स्विच है (जो है, प्लगइन्स हमें वर्ग के तरीकों और गुण को ओवरराइड करते हैं कि समर्थन करता है)। तो, उदाहरण के लिए, यदि आप एक वेब एप्लिकेशन है, तो आप एक प्लगइन रजिस्ट्री हो सकता है, और तुम यहाँ प्लगइन्स को सक्रिय कर सकते हैं। यह भी ध्यान दें Dog_bark_beforeEvent()समारोह। अगर मैं सेट $mixed = 'BLOCK_EVENT'वापसी कथन से पहले, यह भौंकने से कुत्ते को अवरुद्ध कर देगा और यह भी Dog_bark_afterEvent को ब्लॉक कर देगा क्योंकि वहाँ किसी भी घटना नहीं होगा।

भाग 4 में, कि सामान्य ऑपरेशन कोड है, लेकिन लगता है कि क्या आप सोच सकते हैं सब पर ऐसे ही नहीं चलता है चलाना शामिल है। उदाहरण के लिए, कुत्ते Fido ', लेकिन' कोको 'के रूप में यह के नाम की घोषणा नहीं करता है। कुत्ता कहना नहीं है 'म्याऊ', लेकिन 'Woof'। और जब आप बाद में कुत्ते के नाम को देखने के लिए चाहते हैं, तो आप इसके बजाय 'कोको' के 'अलग' है। उन सभी ओवरराइड भाग 3 में प्रदान किया गया।

यह कैसे काम करता है? ठीक है, से इनकार करते हैं eval()(जो हर किसी का कहना है कि "" बुराई है) और शासन है कि यह एक पर्यवेक्षक पैटर्न नहीं है। तो, जिस तरह से यह काम करता है डरपोक खाली वर्ग, प्लगेबल कहा जाता है जो तरीकों और गुण कुत्ता वर्ग द्वारा प्रयोग किया जाता शामिल नहीं करता है। इस प्रकार, कि जब तब होता है, जादू तरीकों हमारे लिए संलग्न करेंगे। इसलिए भागों 3 और 4 वस्तु प्लगेबल वर्ग से प्राप्त के साथ हम मेस में, नहीं कुत्ता वर्ग ही। इसके बजाय, हम प्लगइन वर्ग हमारे लिए कुत्ता वस्तु पर "छू" करते हैं। (यदि है कि डिजाइन पैटर्न के कुछ प्रकार के बारे में मैं नहीं जानता है - तो कृपया मुझे बताएं।)

01/06/2009 को 04:59
का स्रोत उपयोगकर्ता

वोट
7

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

क्या बारे में अगर आप प्लगइन्स एक अलग पर चलाने के लिए चाहते थे - दूरस्थ - सर्वर? यह करने के लिए सबसे अच्छा तरीका है एक रूप है कि आप भिन्न URL है कि जब विशेष घटनाओं अपने आवेदन में होते ही कहा जाता है परिभाषित करने के लिए अनुमति देता है प्रदान करने के लिए किया जाएगा।

अलग घटनाओं घटना है कि सिर्फ हुआ उसके आधार पर अलग अलग जानकारी भेजना होगा।

इस तरह, आप बस URL है, जो (जैसे https पर) अपने आवेदन करने के लिए प्रदान की गई है जहां दूरस्थ सर्वर जानकारी है कि आपके आवेदन द्वारा भेज दिया गया है के आधार पर कार्य कर सकते हैं करने के लिए एक cURL कॉल प्रदर्शन करेंगे।

यह दो लाभ प्रदान करता है:

  1. आप अपने स्थानीय सर्वर पर किसी भी कोड की मेजबानी के लिए की जरूरत नहीं है (सुरक्षा)
  2. कोड अलग अलग भाषाओं में दूरस्थ सर्वर (तानाना) पर हो सकता है अन्य तो पीएचपी (पोर्टेबिलिटी)
22/04/2013 को 06:41
का स्रोत उपयोगकर्ता

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more