上一篇文章中已经说了PHP插件机制的实现理论,这篇文章就主要是附上了一篇例子。本例子也主要借鉴了网上一些网友的方式做了稍微的改造。如果已经了解了原理的朋友可以直接拿来继续改造和使用,如果还不太了解原理的朋友请继续去看一下上一篇文章,文章地址:PHP插件机制写法http://www.chhua.com/web-note4136

好了,不多说了,上例子

test.php 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<span style="color: #000000;font-weight: bold"><?php</span>
<span style="color: #009933;font-style: italic">/** 
* PluginManager Class 
* 
* 插件机制的实现核心类 
* 
* @link http://www.chhua.com/ 
*/</span> 
<span style="color: #000000;font-weight: bold">class</span> PluginManager 
<span style="color: #009900">{</span> 
    <span style="color: #009933;font-style: italic">/** 
     * 监听已注册的插件 
     * 
     * @access private 
     * @var array 
     */</span> 
    <span style="color: #000000;font-weight: bold">private</span> <span style="color: #000088">$_listeners</span> <span style="color: #339933">=</span> <a rel="noopener noreferrer nofollow" href="http://www.php.net/array" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">array</span></a><span style="color: #009900">(</span><span style="color: #009900">)</span><span style="color: #339933">;</span> 
     <span style="color: #009933;font-style: italic">/** 
     * 构造函数 
     *  
     * @access public 
     * @return void 
     */</span> 
    <span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> __construct<span style="color: #009900">(</span><span style="color: #009900">)</span> 
    <span style="color: #009900">{</span> 
        <span style="color: #666666;font-style: italic">#这里$plugin数组包含我们获取已经由用户激活的插件信息 
</span>     <span style="color: #666666;font-style: italic">#为演示方便,我们假定$plugin中至少包含 
</span>     <span style="color: #666666;font-style: italic">#$plugin = array( 
</span>        <span style="color: #666666;font-style: italic">#    'name' => '插件名称', 
</span>        <span style="color: #666666;font-style: italic">#    'directory'=>'插件安装目录' 
</span>        <span style="color: #666666;font-style: italic">#); 
</span>     
 
      <span style="color: #666666;font-style: italic">//  $plugins = get_active_plugins();#这个函数请自行实现 </span>
 
        <span style="color: #666666;font-style: italic">//函数实现后的最终数据结构效果如下</span>
        <span style="color: #000088">$plugins</span><span style="color: #339933">=</span><a rel="noopener noreferrer nofollow" href="http://www.php.net/array" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">array</span></a><span style="color: #009900">(</span><a rel="noopener noreferrer nofollow" href="http://www.php.net/array" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">array</span></a><span style="color: #009900">(</span><span style="color: #0000ff">"directory"</span><span style="color: #339933">=></span><span style="color: #0000ff">"demo"</span><span style="color: #339933">,</span>
        <span style="color: #0000ff">"name"</span><span style="color: #339933">=></span><span style="color: #0000ff">"DEMO"</span><span style="color: #009900">)</span><span style="color: #009900">)</span><span style="color: #339933">;</span>
 
 
        <span style="color: #b1b100">if</span><span style="color: #009900">(</span><span style="color: #000088">$plugins</span><span style="color: #009900">)</span> 
        <span style="color: #009900">{</span> 
            <span style="color: #b1b100">foreach</span><span style="color: #009900">(</span><span style="color: #000088">$plugins</span> <span style="color: #b1b100">as</span> <span style="color: #000088">$plugin</span><span style="color: #009900">)</span> 
 
            <span style="color: #009900">{</span><span style="color: #666666;font-style: italic">//假定每个插件文件夹中包含一个actions.php文件,它是插件的具体实现 </span>
                <span style="color: #b1b100">if</span> <span style="color: #009900">(</span><span style="color: #339933">@</span><a rel="noopener noreferrer nofollow" href="http://www.php.net/file_exists" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">file_exists</span></a><span style="color: #009900">(</span>STPATH <span style="color: #339933">.</span><span style="color: #0000ff">'plugins/'</span><span style="color: #339933">.</span><span style="color: #000088">$plugin</span><span style="color: #009900">[</span><span style="color: #0000ff">'directory'</span><span style="color: #009900">]</span><span style="color: #339933">.</span><span style="color: #0000ff">'/actions.php'</span><span style="color: #009900">)</span><span style="color: #009900">)</span> 
                <span style="color: #009900">{</span> 
                    <span style="color: #b1b100">include_once</span><span style="color: #009900">(</span>STPATH <span style="color: #339933">.</span><span style="color: #0000ff">'plugins/'</span><span style="color: #339933">.</span><span style="color: #000088">$plugin</span><span style="color: #009900">[</span><span style="color: #0000ff">'directory'</span><span style="color: #009900">]</span><span style="color: #339933">.</span><span style="color: #0000ff">'/actions.php'</span><span style="color: #009900">)</span><span style="color: #339933">;</span> 
                    <span style="color: #000088">$class</span> <span style="color: #339933">=</span> <span style="color: #000088">$plugin</span><span style="color: #009900">[</span><span style="color: #0000ff">'name'</span><span style="color: #009900">]</span><span style="color: #339933">.</span><span style="color: #0000ff">'_actions'</span><span style="color: #339933">;</span> 
                    <span style="color: #b1b100">if</span> <span style="color: #009900">(</span><a rel="noopener noreferrer nofollow" href="http://www.php.net/class_exists" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">class_exists</span></a><span style="color: #009900">(</span><span style="color: #000088">$class</span><span style="color: #009900">)</span><span style="color: #009900">)</span>  
                    <span style="color: #009900">{</span> 
                        <span style="color: #666666;font-style: italic">//初始化所有插件 </span>
                        <span style="color: #666666;font-style: italic">//$this 是本类的引用</span>
                       <span style="color: #000000;font-weight: bold">new</span> <span style="color: #000088">$class</span><span style="color: #009900">(</span><span style="color: #000088">$this</span><span style="color: #009900">)</span><span style="color: #339933">;</span> 
                    <span style="color: #009900">}</span> 
                <span style="color: #009900">}</span> 
            <span style="color: #009900">}</span> 
        <span style="color: #009900">}</span> 
        <span style="color: #666666;font-style: italic">#此处做些日志记录方面的东西 
</span>    <span style="color: #009900">}</span> 
 
    <span style="color: #009933;font-style: italic">/** 
     * 注册需要监听的插件方法(钩子) 
     * 
     * @param string $hook 
     * @param object $reference 
     * @param string $method 
     */</span> 
    <span style="color: #000000;font-weight: bold">function</span> register<span style="color: #009900">(</span><span style="color: #000088">$hook</span><span style="color: #339933">,</span> <span style="color: #339933">&</span><span style="color: #000088">$reference</span><span style="color: #339933">,</span> <span style="color: #000088">$method</span><span style="color: #009900">)</span> 
    <span style="color: #009900">{</span> 
        <span style="color: #666666;font-style: italic">//获取插件要实现的方法 </span>
        <span style="color: #000088">$key</span> <span style="color: #339933">=</span> <a rel="noopener noreferrer nofollow" href="http://www.php.net/get_class" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">get_class</span></a><span style="color: #009900">(</span><span style="color: #000088">$reference</span><span style="color: #009900">)</span><span style="color: #339933">.</span><span style="color: #0000ff">'->'</span><span style="color: #339933">.</span><span style="color: #000088">$method</span><span style="color: #339933">;</span> 
        <span style="color: #666666;font-style: italic">//将插件的引用连同方法push进监听数组中 </span>
        <span style="color: #000088">$this</span><span style="color: #339933">-></span>_listeners<span style="color: #009900">[</span><span style="color: #000088">$hook</span><span style="color: #009900">]</span><span style="color: #009900">[</span><span style="color: #000088">$key</span><span style="color: #009900">]</span> <span style="color: #339933">=</span> <a rel="noopener noreferrer nofollow" href="http://www.php.net/array" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">array</span></a><span style="color: #009900">(</span><span style="color: #339933">&</span><span style="color: #000088">$reference</span><span style="color: #339933">,</span> <span style="color: #000088">$method</span><span style="color: #009900">)</span><span style="color: #339933">;</span> 
        <span style="color: #666666;font-style: italic">#此处做些日志记录方面的东西 
</span>    <span style="color: #009900">}</span> 
    <span style="color: #009933;font-style: italic">/** 
     * 触发一个钩子 
     * 
     * @param string $hook 钩子的名称 
     * @param mixed $data 钩子的入参 
     *    @return mixed 
     */</span> 
    <span style="color: #000000;font-weight: bold">function</span> trigger<span style="color: #009900">(</span><span style="color: #000088">$hook</span><span style="color: #339933">,</span> <span style="color: #000088">$data</span><span style="color: #339933">=</span><span style="color: #0000ff">''</span><span style="color: #009900">)</span> 
    <span style="color: #009900">{</span> 
        <span style="color: #000088">$result</span> <span style="color: #339933">=</span> <span style="color: #0000ff">''</span><span style="color: #339933">;</span> 
        <span style="color: #666666;font-style: italic">//查看要实现的钩子,是否在监听数组之中 </span>
        <span style="color: #b1b100">if</span> <span style="color: #009900">(</span><a rel="noopener noreferrer nofollow" href="http://www.php.net/isset" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">isset</span></a><span style="color: #009900">(</span><span style="color: #000088">$this</span><span style="color: #339933">-></span>_listeners<span style="color: #009900">[</span><span style="color: #000088">$hook</span><span style="color: #009900">]</span><span style="color: #009900">)</span> <span style="color: #339933">&&</span> <a rel="noopener noreferrer nofollow" href="http://www.php.net/is_array" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">is_array</span></a><span style="color: #009900">(</span><span style="color: #000088">$this</span><span style="color: #339933">-></span>_listeners<span style="color: #009900">[</span><span style="color: #000088">$hook</span><span style="color: #009900">]</span><span style="color: #009900">)</span> <span style="color: #339933">&&</span> <a rel="noopener noreferrer nofollow" href="http://www.php.net/count" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">count</span></a><span style="color: #009900">(</span><span style="color: #000088">$this</span><span style="color: #339933">-></span>_listeners<span style="color: #009900">[</span><span style="color: #000088">$hook</span><span style="color: #009900">]</span><span style="color: #009900">)</span> <span style="color: #339933">></span> <span style="color: #cc66cc">0</span><span style="color: #009900">)</span> 
        <span style="color: #009900">{</span> 
            <span style="color: #666666;font-style: italic">// 循环调用开始 </span>
            <span style="color: #b1b100">foreach</span> <span style="color: #009900">(</span><span style="color: #000088">$this</span><span style="color: #339933">-></span>_listeners<span style="color: #009900">[</span><span style="color: #000088">$hook</span><span style="color: #009900">]</span> <span style="color: #b1b100">as</span> <span style="color: #000088">$listener</span><span style="color: #009900">)</span> 
            <span style="color: #009900">{</span> 
                <span style="color: #666666;font-style: italic">// 取出插件对象的引用和方法 </span>
                <span style="color: #000088">$class</span> <span style="color: #339933">=&</span> <span style="color: #000088">$listener</span><span style="color: #009900">[</span><span style="color: #cc66cc">0</span><span style="color: #009900">]</span><span style="color: #339933">;</span> 
                <span style="color: #000088">$method</span> <span style="color: #339933">=</span> <span style="color: #000088">$listener</span><span style="color: #009900">[</span><span style="color: #cc66cc">1</span><span style="color: #009900">]</span><span style="color: #339933">;</span> 
                <span style="color: #b1b100">if</span><span style="color: #009900">(</span><a rel="noopener noreferrer nofollow" href="http://www.php.net/method_exists" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">method_exists</span></a><span style="color: #009900">(</span><span style="color: #000088">$class</span><span style="color: #339933">,</span><span style="color: #000088">$method</span><span style="color: #009900">)</span><span style="color: #009900">)</span> 
                <span style="color: #009900">{</span> 
                    <span style="color: #666666;font-style: italic">// 动态调用插件的方法 </span>
                    <span style="color: #000088">$result</span> <span style="color: #339933">.=</span> <span style="color: #000088">$class</span><span style="color: #339933">-></span><span style="color: #000088">$method</span><span style="color: #009900">(</span><span style="color: #000088">$data</span><span style="color: #009900">)</span><span style="color: #339933">;</span> 
                <span style="color: #009900">}</span> 
            <span style="color: #009900">}</span> 
        <span style="color: #009900">}</span> 
        <span style="color: #666666;font-style: italic">#此处做些日志记录方面的东西 
</span>        <span style="color: #b1b100">return</span> <span style="color: #000088">$result</span><span style="color: #339933">;</span> 
    <span style="color: #009900">}</span> 
<span style="color: #009900">}</span> 
 
<a rel="noopener noreferrer nofollow" href="http://www.php.net/define" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">define</span></a><span style="color: #009900">(</span>STPATH<span style="color: #339933">,</span> <span style="color: #0000ff">"./"</span><span style="color: #009900">)</span><span style="color: #339933">;</span>
 
<span style="color: #000088">$pluginManager</span><span style="color: #339933">=</span><span style="color: #000000;font-weight: bold">new</span> PluginManager<span style="color: #009900">(</span><span style="color: #009900">)</span><span style="color: #339933">;</span>
 
<span style="color: #000088">$pluginManager</span><span style="color: #339933">-></span><span style="color: #004000">trigger</span><span style="color: #009900">(</span><span style="color: #0000ff">"demo"</span><span style="color: #009900">)</span><span style="color: #339933">;</span>

demo插件文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<span style="color: #000000;font-weight: bold"><?php</span>
<span style="color: #009933;font-style: italic">/**
 * 这是一个Hello World简单插件的实现
 *
 * @link        http://www.chhua.com/
 */</span>
<span style="color: #009933;font-style: italic">/**
 *需要注意的几个默认规则:
 *    1. 本插件类的文件名必须是action
 *    2. 插件类的名称必须是{插件名_actions}
 */</span>
<span style="color: #000000;font-weight: bold">class</span> DEMO_actions
<span style="color: #009900">{</span>
    <span style="color: #666666;font-style: italic">//解析函数的参数是pluginManager的引用</span>
    <span style="color: #000000;font-weight: bold">function</span> __construct<span style="color: #009900">(</span><span style="color: #339933">&</span><span style="color: #000088">$pluginManager</span><span style="color: #009900">)</span>
    <span style="color: #009900">{</span>
        <span style="color: #666666;font-style: italic">//注册这个插件</span>
        <span style="color: #666666;font-style: italic">//第一个参数是钩子的名称</span>
        <span style="color: #666666;font-style: italic">//第二个参数是pluginManager的引用</span>
        <span style="color: #666666;font-style: italic">//第三个是插件所执行的方法</span>
        <span style="color: #000088">$pluginManager</span><span style="color: #339933">-></span><span style="color: #004000">register</span><span style="color: #009900">(</span><span style="color: #0000ff">'demo'</span><span style="color: #339933">,</span> <span style="color: #000088">$this</span><span style="color: #339933">,</span> <span style="color: #0000ff">'say_hello'</span><span style="color: #009900">)</span><span style="color: #339933">;</span>
    <span style="color: #009900">}</span>
 
    <span style="color: #000000;font-weight: bold">function</span> say_hello<span style="color: #009900">(</span><span style="color: #009900">)</span>
    <span style="color: #009900">{</span>
        <span style="color: #b1b100">echo</span> <span style="color: #0000ff">'Hello World'</span><span style="color: #339933">;</span>
    <span style="color: #009900">}</span>
<span style="color: #009900">}</span>