thinkphp如何利用反射实现钩子方法

ThinkPHP框架的控制器模块是如何实现 前控制器、后控制器,及如何执行带参数的方法?

PHP系统自带的 ReflectionClass、ReflectionMethod 类,可以反射用户自定义类的中属性,方法的权限和参数等信息,通过这些信息可以准确的控制方法的执行。

ReflectionClass:  [PHP手册]详情

主要用的方法:

hasMethod(string)  是否存在某个方法

getMethod(string)  获取方法

ReflectionMethod:  [PHP手册]详情

主要方法:

isPublic()    是否为 public 方法

getNumberOfParameters()  获取参数个数

getParamters()  获取参数信息

invoke( object $object [, mixed $parameter [, mixed $... ]] ) 执行方法  

invokeArgs(object obj, array args)     带参数执行方法

 实例演示

<?php

class BlogAction {



	public function detail() {

		echo 'detail' . "\r\n";

	}



	public function test($year = 2014, $month = 4, $day = 21) {

		echo $year . '--' . $month . '--' . $day . "\r\n";

	}



	public function _before_detail() {

		echo __FUNCTION__ . "\r\n";

	}



	public function _after_detail() {

		echo __FUNCTION__ . "\r\n";

	}

}



// 执行detail方法

$method = new ReflectionMethod('BlogAction', 'detail');

$instance = new BlogAction();



// 进行权限判断

if ($method->isPublic()) {



	$class = new ReflectionClass('BlogAction');



	// 执行前置方法

	if ($class->hasMethod('_before_detail')) {

		$beforeMethod = $class->getMethod('_before_detail');

		if ($beforeMethod->isPublic()) {

			$beforeMethod->invoke($instance);

		}

	}



	$method->invoke(new BlogAction);



	// 执行后置方法

	if ($class->hasMethod('_after_detail')) {

		$beforeMethod = $class->getMethod('_after_detail');

		if ($beforeMethod->isPublic()) {

			$beforeMethod->invoke($instance);

		}

	}

}



// 执行带参数的方法

$method = new ReflectionMethod('BlogAction', 'test');

$params = $method->getParameters();

foreach ($params as $param) {

	$paramName = $param->getName();

	if (isset($_REQUEST[$paramName])) {

		$args[] = $_REQUEST[$paramName];

	} elseif ($param->isDefaultValueAvailable()) {

		$args[] = $param->getDefaultValue();

	}

}



if (count($args) == $method->getNumberOfParameters()) {

	$method->invokeArgs($instance, $args);

} else {

	echo 'parameters is wrong!';

}

 

另一段代码参考 

/**

 * 执行App控制器

 */

public function execApp() {



	// 创建action控制器实例

	$className = MODULE_NAME . 'Controller';

	$namespaceClassName = '\\apps\\' . APP_NAME . '\\controller\\' . $className;

	load_class($namespaceClassName, false);



	if (!class_exists($namespaceClassName)) {

		throw new \Exception('Oops! Module not found : ' . $namespaceClassName);

	}



	$controller = new $namespaceClassName();



	// 获取当前操作名

	$action = ACTION_NAME;



	// 执行当前操作

	//call_user_func(array(&$controller, $action)); // 其实吧,用这个函数足够啦!!!

	try {

		$methodInfo = new \ReflectionMethod($namespaceClassName, $action);

		if ($methodInfo->isPublic() && !$methodInfo->isStatic()) {

			$methodInfo->invoke($controller);

		} else { // 操作方法不是public类型,抛出异常

			throw new \ReflectionException();

		}

	} catch (\ReflectionException $e) {

		// 方法调用发生异常后,引导到__call方法处理

		$methodInfo = new \ReflectionMethod($namespaceClassName, '__call');

		$methodInfo->invokeArgs($controller, array($action, ''));

	}

	return;

}

本文转自http://blog.snsgou.com/post-47.html

你可能感兴趣的:(thinkphp)