允许插入PHP应用程序的最佳方法

我开始使用PHP创建一个新的Web应用程序,这一次我想创建一些人们可以使用插件接口来扩展的东西。

如何在代码中编写“钩子”,以便插件可以附加到特定的事件?

你可以使用Observer模式。一个简单的功能方法来完成这个:

<?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 applicationn";
$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中完成插件系统的一种方法。有更好的选择,我建议你检查一下WordPress文档以获取更多信息。

抱歉,下划线字符被Markdown替换为HTML实体?当这个错误得到解决时,我可以重新发布这个代码。

编辑:没关系,只有当你编辑_

时才会出现这种情况 假设你不需要Observer模式,因为它需要你改变你的类方法来处理监听的任务,并且需要一些通用的东西。假设您不想使用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);
        }   
     大专栏  允许插入PHP应用程序的最佳方法    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部分中,您可能会在PHP脚本的顶部使用require_once()调用包含这些内容。它加载类来创建可插入的类。

在第2部分中,这是我们加载类的地方。请注意,我不必为课程做任何特殊的事情,这与观察者模式明显不同。

在第3部分中,我们将类切换为“可插入”(即,支持让我们覆盖类方法和属性的插件)。所以,举例来说,如果你有一个网络应用程序,你可能有一个插件注册表,你可以在这里激活插件。还要注意Dog_bark_beforeEvent()函数。如果我在返回语句之前设置了$ mixed ='BLOCK_EVENT',它会阻止狗叫,也会阻止Dog_bark_afterEvent,因为不会有任何事件发生。

在第4部分中,这是正常的操作代码,但请注意,您可能会认为运行的代码根本就不会运行。例如,狗没有宣布它的名字是’Fido’,而是’Coco’。狗不会说’喵’,而是’Woof’。而当你想看看狗的名字后,你会发现它是’不同’,而不是’可可’。所有这些重写都在第3部分中提供。

那么这是如何工作的?那么,让我们排除eval()(每个人都说“邪恶”),并排除它不是Observer模式。所以,它的工作方式是被称为Pluggable的空洞类,它不包含Dog类使用的方法和属性。因此,既然发生了,魔法就会为我们搞。这就是为什么在第3部分和第4部分中,我们混淆了从Pluggable类派生的对象,而不是Dog类本身。相反,我们让Plugin类为我们做了Dog对象的“触摸”。
(如果这是某种设计模式,我不知道 - 请让我知道。)

未经作者同意,本文严禁转载,违者必究!

猜你喜欢

转载自www.cnblogs.com/sanxiandoupi/p/11724395.html