插件自定义方法
<?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);