目录

反射

PHP的反射类。

Reflection

class Person
{
    public $name;
    public $gender;
    public function say(){
        echo $this->name, " is ", $this->gender, PHP_EOL;
    }

    public function __set( $name, $value ){
        echo "Setting $name to $value" , PHP_EOL;
        $this -> $name = $value;
    }

    public function __get( $name ) {
        if ( !isset($this->$name) ){
            echo "未设置";
            $this -> $name = "默认值";
        }
        return $this->$name;
    }

    public function __call($name, $args){
        echo $name, " called ", PHP_EOL;
    }
}
$s = new Person();
$s -> name = 'Link';
$s -> gender = 'male';
$s -> age = 24;

$reflect = new ReflectionObject($s);
var_dump( $reflect -> getProperties() );
var_dump( $reflect -> getMethods() );
var_dump(get_object_vars($s));
var_dump(get_class_vars(get_class($s)));
var_dump(get_class_methods(get_class($s)));

$obj = new ReflectionClass('Person');
print_r( $obj -> getName() );
print_r( $obj -> getProperties() );
print_r( $obj -> getMethods() );

使用反射实现动态代理:

class mysql {
    function connect( $db ) {
        echo "connect to db[0]", PHP_EOL;
    }
}
class sqlproxy {
    private $target;
    function __construct($tar){
        $this -> target[] = new $tar();
    }
    function __call($name, $args){
        foreach ($this -> target as $obj) {
            $r = new ReflectionClass($obj);
            if( $method = $r -> getMethod($name) ){
                if( $method -> isPublic() && !$method->isAbstract()) {
                    echo "before invoke ...", PHP_EOL;
                    $method->invoke($obj,$args);
                    echo "after invoke ...", PHP_EOL;
                }
            }
        }
    }
}
$obj = new sqlproxy('mysql');
$obj -> connect('member');

PHP 提供的反射类的相关知识

Reflection          为类的摘要信息提供静态函数
ReflectionClass     类信息和工具
ReflectionMethod    提供类方法信息
ReflectionParameter 提供方法的参数信息
ReflectionProperty  类属性信息
ReflectionFunction  函数信息和工具
ReflectionExtension PHP扩展信息
ReflectionException 错误类

这些反射类可以在运行时访问对象、函数和脚本中的扩展信息

<?php
interface Module {
    function execute();
}

class Person{
    public $name;
    function __construct($name){
        $this -> name = $name;
    }
}

class FtpModule implements Module {
    function setHost( $host ){
        print "Ftpmodule::setHost() : $host \n";
    }

    function setUser( $user ){
        print "FtpModule::setUser() : $user \n";
    }

    function execute(){
        // do something
    }
}

class PersonModule implements Module {
    function setPerson( Person $person){
        print "PersonModule::setPerson(): {$person -> name} \n";
    }

    function execute(){
        // do something
    }
}

class ModuleRunner {
    private $configData = [
        'PersonModule' => ['person'=>'bob'],
        'FtpModule' => ['host'=>'example.com','user'=>'anon']
    ];

    private $modules = [];

    function init(){
        $interface = new ReflectionClass('Module');
        var_dump($interface);
        foreach ( $this -> configData as $modulename => $params ){
            $module_class = new ReflectionClass( $modulename );

            if( ! $module_class -> isSubclassOf($interface)){
                throw new Exception("Unkown module type : $modulename");
            }

            $module = $module_class -> newInstance();
            foreach( $module_class -> getMethods() as $method ) {
                $this -> handleMethod($module , $method , $params);
            }
            array_push($this -> modules,$module);
        }
    }

    function handleMethod(Module $module , ReflectionMethod $method,$params ){
        $name = $method -> getName();
        $args = $method -> getParameters();

        if(count($args) != 1 || substr($name,0,3) != 'set'){
            return false;
        }

        $property = strtolower(substr($name,3));

        if(!isset($params[$property])){
            return false;
        }

        $arg_class = $args[0] -> getClass();

        if(empty($arg_class)){
            $method -> invoke($module , $params[$property]);
        }else{
            $method -> invoke($module , $arg_class -> newInstance($params[$property]));
        }
    }
}

$test = new ModuleRunner();
$test -> init();

类反射

为了在不看类内部实现的情况下,深入了解一个类!

class A{
    const A = 'i am const A';
    private $a = "aaa";
    public function hehe(){
        echo "heheh";
    }
}
$prod_class = new ReflectionClass('A');
Reflection::export($prod_class);