下例为官方文档,来认识一下反射
function bar(Exception $a, &$b, $c) { }
$reflect = new ReflectionFunction('bar');
#$reflect object(ReflectionFunction)#1 (1) { ["name"]=> string(3) "bar" }
foreach ($reflect->getParameters() as $i => $param) {
#循环的第一次输出param object(ReflectionParameter)#2 (1) { ["name"]=> string(1) "a" }
printf(
"-- Parameter #%d: %s {\n".
" Class: %s\n".
" Allows NULL: %s\n".
" Passed to by reference: %s\n".
" Is optional?: %s\n".
"}\n",
$i,
$param->getName(),#得到参数名 a
var_export($param->getClass(), 1),
#$param->getClass()输出为ReflectionClass::__set_state(array(
'name' => 'Exception',
))
var_export($param->allowsNull(), 1), #参数是否可以为空,可以为空返回true;
var_export($param->isPassedByReference(), 1),#如果参数是按引用传递,返回true;
$param->isOptional() ? 'yes' : 'no'
);
exit;
}
?>
下例为laravel的依赖注入原理,代码来自https://phphub.org/topics/843;
<?php
namespace Database;
use ReflectionMethod;
class Database
{
protected $adapter;
public function __construct ()
{}
public function test (MysqlAdapter $adapter)
{
$adapter->test();
}
}
class MysqlAdapter
{
public function test ()
{
echo "i am MysqlAdapter test";
}
}
class app
{
public static function run ($instance, $method)
{
if (! method_exists($instance, $method))
return null;
$reflector = new ReflectionMethod($instance, $method);
#$reflector object(ReflectionMethod)#2 (2) { ["name"]=> string(4) "test" ["class"]=> string(17) "Database\Database" }
$parameters = [
1
];
foreach ($reflector->getParameters() as $key => $parameter)
#此处获得$method方法的需要的参数
#$parameter object(ReflectionParameter)#3 (1) { ["name"]=> string(7) "adapter" }
{
$class = $parameter->getClass();
if ($class)
{
array_splice($parameters, $key, 0, [
new $class->name()
]);#根据$method需要的参数,通过$class->name获得此参数的类型,然后生成一个此类型的对象,$parameters的开头处插入MysqlAdapter类型的对象 即$parameters=[MysqlAdapter对象,1]
}
}
call_user_func_array([
$instance,
$method
], $parameters);#调用$instance对象下的$method方法,将$parameters作为参数传递
}
}
app::run(new Database(), 'test');
总结:使用反射的意义在于,当传入一个对象和此对象包含的方法时;laravel通过反射来获取到此方法的参数列表,同时获取到参数的具体类型,然后根据此类型,生成对应的对象,供方法使用。