插件,钩子用法

插件自定义方法

<?php
if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME']))
{
    include_once '../configs/config.ini.php';
}

/**
 * 插件管理类,设置为单例模式
 * 
 * 
 * @category   Framework
 * @package    Plugin
 * @author     Yf <service@yuanfeng.cn>
 * @copyright  Copyright (c) 2010 远丰仁商
 * @version    1.0
 * @todo       
 */
class Yf_Plugin_Manager
{
    private static $_instance ; 

    /**
     * 监听已注册的插件
     *
     * @access private
     * @staticvar array
     */
    private static $_listeners = array();

    /**
     * 构造方法
     */
    private function __construct()
    {
    }

    final public static function getInstance() 
    {
        if (!(self::$_instance instanceof self))
        {
            self::$_instance = new self();

			$args = func_get_args();
			//call_user_func_array是利用回调函数处理数组
			//
			call_user_func_array(array(self::$_instance, 'init'), $args);
        }

        return self::$_instance;
    }
    
    /**
     * 注册需要监听的插件方法(钩子)
     *
     * @param string $hook
     * @param object $reference
     * @param string $method
     */
    public function register($hook, &$reference, $method)
    {
        //获取插件要实现的方法
        $key = get_class($reference).'->'.$method;

        //将插件的引用连同方法push进监听数组中
        self::$_listeners[$hook][$key] = array(&$reference, $method);

        #此处做些日志记录方面的东西

        return self::$_instance;
    }

    /**
     * 触发一个钩子
     *
     * @param string $hook 钩子的名称
     * @param mixed $data 钩子的入参
     * @return mixed
     */
    public function trigger()
    {
        $args = func_get_args();
        $hook = array_shift($args);
        $result = '';

        //查看要实现的钩子,是否在监听数组之中
        if (isset(self::$_listeners[$hook]) && is_array(self::$_listeners[$hook]) && count(self::$_listeners[$hook]) > 0)
        {
            // 循环调用开始
            foreach (self::$_listeners[$hook] as $plugin_name=>$listener)
            {
                // 取出插件对象的引用和方法
                $class = &$listener[0];
                $method = &$listener[1];

                if(method_exists($class, $method))
                {
                    // 动态调用插件的方法
                    $plugin_name = get_class($class) . '_' . $method;
                    //$result[$plugin_name] = $class->$method($data);

                    $result[$plugin_name] =  call_user_func_array(array($class, $method), $args);
                    //$data = $result[$plugin_name];
                }
            }
        }

        #此处做些日志记录方面的东西

        return $result;
    }

    /**
     * 初始化函数
     * 
     * @param array $plugin_rows 激活插件数组
     * $plugin = array(
     *     'name' => '插件名称',
     *     'directory'=>'插件安装目录'plugins
     * );
     * @access private
     * @return void
     */
    public function init($plugin_rows=array())
    {
        if($plugin_rows)
        {
            foreach($plugin_rows as $plugin)
            {
                if (isset($plugin['cli']) && false==$plugin['cli'])
                {
                    if ('cli' == SAPI)
                    {
                        continue;
                    }
                }
                
                //插件文件夹中包含一个{'Plugin/' . $plugin['name'] .php}文件,它是插件的具体实现
                $class = 'Plugin_' . $plugin['name'];
                $plugin_path = CTL_PATH . '/Plugin/' . $plugin['name'] . '.php';

                if (is_file($plugin_path))
                {
                    include_once($plugin_path);

                    if (class_exists($class, false)) 
                    {
                        //初始化所有插件
                        //可以交给插件自己负责,目前这样,框架结构规则严格
                        new $class();
                    }
                    else
                    {
                        //报错。
                    }
                }
                else
                {
					Yf_Log::log(sprintf(_('插件 %s 不存在!'), $plugin['name']), Yf_Log::INFO);
                }
            }
        }

        #此处做些日志记录方面的东西
    }

    final private function __clone() 
    {
    } 
}

?>

call_user_func_array 更多用法

// 调用类中的静态方法
   // 类名方法名以数据形式
call_user_func(['Test', 'demo'], 1, 2); // 3
call_user_func_array(['Test', 'demo'], [1, 2]); // 3
   // 类名方法名以字符串形式
call_user_func('Test::demo', 1, 2); // 3
call_user_func_array('Test::demo', [1, 2]); // 3

// 调用类中的动态方法,对象和方法必须通过数组形式传递
call_user_func([new Test, 'show'], 1, 2); // 3
call_user_func_array([new Test, 'show'], [1, 2]); // 3

用户认证代码

<?php

//用户登录认证
class Plugin_Perm implements Yf_Plugin_Interface
{
    //解析函数的参数是pluginManager的引用
    function __construct()
    {
        //注册这个插件
        //第一个参数是钩子的名称
        //第二个参数是pluginManager的引用
        //第三个是插件所执行的方法
        Yf_Plugin_Manager::getInstance()->register('perm', $this, 'checkPerm');
        Yf_Plugin_Manager::getInstance()->register('server_state', $this, 'checkServerState');
        
    }

	function desc()
    {
        echo 'Hello World';
    }

    public function checkPerm()
    {
        $data = new Yf_Data();

		//无需权限判断的文件
		$not_perm = array('Login','Api', 'Licence');

		//不需要登录
		if (!isset($_REQUEST['ctl']) || (isset($_REQUEST['ctl']) && in_array($_REQUEST['ctl'], $not_perm)))
		{
			//
		}
        elseif (Perm::checkUserPerm())
        {
			/*
			if (!Perm::checkUserRights())
			{
				//无权限
				fb($_REQUEST, '-2:无访问权限', FirePHP::ERROR);
				$data->setError(_('无访问权限'));
				return $this->outputError($data);
			}
			*/
        }
        else
        {

            location_to(Yf_Registry::get('url') . '?ctl=Login');
			//$data->setError(_('需要登录'), 30);
            //return $this->outputError($data);
        }
    }

    public function outputError($data)
    {
        $d = $data->getDataRows();

        $protocol_data = Yf_Data::encodeProtocolData($d);
        echo $protocol_data;

        exit();
    }
}

重点分析

1,这里注册了名字为perm的钩子
2,查找perm在哪里被触发了(trigger)

  function __construct()
    {
        //注册这个插件
        //第一个参数是钩子的名称
        //第二个参数是pluginManager的引用
        //第三个是插件所执行的方法
        Yf_Plugin_Manager::getInstance()->register('perm', $this, 'checkPerm');
        Yf_Plugin_Manager::getInstance()->register('server_state', $this, 'checkServerState');
        
    }

3,通过debug可以看到

//插件启动
$plugin_rows = array(
	array('name'=>'Perm'),
	array('name'=>'Log'),
	array('name'=>'Xhprof'),
);

$PluginManager = Yf_Plugin_Manager::getInstance($plugin_rows);
$PluginManager->trigger('init', '');

Yf_Registry::set('hook', $PluginManager);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值