Home  >  Article  >  Backend Development  >  Detailed code examples of PHP reflection technology (pictures and texts)

Detailed code examples of PHP reflection technology (pictures and texts)

黄舟
黄舟Original
2017-03-11 10:23:443008browse

Summary

Compared with Java's reflection, reflection in PHP is really a work of conscience. Although from a maintenance perspective, Java is superior and has more advantages. However, the cumbersome processing also adds a certain learning cost to Java's reflection mechanism.

Today I tried to use PHP's reflection technology to obtain class information.
The core operations can be seen in the official help document of PHP. The most commonly used one here is

getProperties
getMethods

Detailed code examples of PHP reflection technology (pictures and texts)

target class

For better To demonstrate the results and maintenance of reflection, let's create a class first. The directory structure is as follows:
Detailed code examples of PHP reflection technology (pictures and texts)

<?phpclass Person {
    private $name;    private $age;    private $address;    public function __construct($name, $age, $address) {
        $this->name = $name;        $this->age = $age;        $this->address = $address;
    }    public function setter($key, $value) {
        exec ( "{$this}->" . $key . "={$value}" );
    }    /**
     * 通配型的getter方法不好用。
     * <br />
     * 原因: Object Person can not be converted to string.
     * 
     * @param unknown $key         
     * @return string
     */
    public function getter($key) {
        return exec ( "$this" . "->{$key}" );
    }    /**
     * 模拟Java语言实现的getter方法。<br />
     *
     * 缺点: 需要为每一个private属性提供单独的getter方法,使得代码略显臃肿。
     */
    public function getName() {
        return $this->name;
    }
}class Grade {
    private $name;    public function __construct($name) {
        $this->name = $name;
    }    public function setName($name) {
        $this->name = $name;
    }    public function getName() {
        return $this->name;
    }
}

Loading problem

Loading mechanism

is officially in progress Before the reflection operation, let’s first discuss the __autoload automatic loading mechanism. As the name suggests, it automatically loads (classes, or other PHP files).

For a deeper level, this involves the working principle of the PHP interpreter. In other words, we cannot only write one PHP file for a project. On the contrary, there may be hundreds of PHP files in a project, and they will inevitably call each other.

In other words, we declared and implemented an addition function in file A, but it needs to be called in file B. Obviously this addition is not implemented in the B file at all, so the PHP interpreter cannot perform the addition operation.

At this time, you need to let the PHP interpreter know how to do this addition, so you need require / include The A file that contains this addition function.

In this way, the PHP interpreter knows how to interpret and run our PHP files.


Similar to PHP, in the Java language we only need to add the import statement in front of the source file, and the Java virtual machine will automatically add the relevant class information. Moreover, strongly typed Java can detect such problems before compilation, so the code maintenance is more convenient. PHP requires manual include/require.

But it should be clear that the two are just changing the soup without changing the medicine.

Auto-loading mechanism

But if you manually load each php file to be referenced, you may have to write multiple such loading statements. Therefore, in order to facilitate the handling of this problem, PHP5 introduced an automatic loading mechanism.

void __autoload ( string $class )

$class is the name of the class to be loaded. Please note that it is the name of class.


how to use?

Since the automatic loading mechanism is so good, how do we use it?

The answer is to add a custom __autoload($class) function in PHP that needs to load other class files. Let’s take the file AB just now as an example.

There is a written class Person in file A, which needs to be used in file B. At this time, just add a __aotoload function in file B. Moreover, the writing method of this function is relatively simple (if everything is designed according to the simplest idea).

function __autoload($class) {
    $filename = "$class.class.php";    
    if(!file_exists($filename)){        
    throw new RuntimeException("$filename 文件不存在!");
    }else {        require "$filename";
    }
}

The PHP interpreter will first check when scanning file B. If the target class Person is not introduced, it will determine whether __autoload is implemented. If it exists, the automatic loading function will be used. Load, otherwise an error will be reported and exit.

Attention

Although the above automatic loading function is relatively simple, in reality it requires a lot of "price", that is, the name of the loaded class file must be consistent with the class Consistent (no need to be case sensitive). Such as:

要加载的类的名称为Person,
则该类所在的文件的名称需要为person.class.php,或者Person.class.php

Moreover, the path problem is also a relatively difficult problem. It is not difficult to see in this simple automatic loading function. Here they are located in the same directory. Imagine the situation when this condition is not met. You can know how large the amount of code this automatic loading function will be.

In this case, it will also violate the original intention of the design of the automatic loading mechanism. Therefore, it is very necessary to store related class files according to a specific directory structure.

The so-called: It adds redundant features, but brings the benefit of easy maintenance.

Personally, I think it is better to maintain the PHP program according to the directory structure of the Java language, which will yield unexpected gains.

Reflection

The following officially enters the topic of reflection, which has been mentioned in the summary section. The key point lies in the use of ReflectionClass.

Reflection properties

<?phprequire &#39;./bean/beans.php&#39;;
// Person 在beans.php文件中声明$protype = new ReflectionClass("Person");
// 可以添加一个参数,来进行过滤操作。如只获取public类型的属性
$properties = $protype->getProperties();
// 反射获取到类的属性信息
foreach ($properties as $property) {    
echo $property."<br />";
}

Detailed code examples of PHP reflection technology (pictures and texts)

Compared to Java, PHP is simpler to obtain private attributes.

Reflection method

<?php
require &#39;./bean/beans.php&#39;;
$protype = new ReflectionClass("Person");
$methods = $protype->getMethods();
foreach ($methods as $method) {    
echo $method->getName()."<br />";
}

Detailed code examples of PHP reflection technology (pictures and texts)

In addition, you can also add filter conditions. Just give the getMethods method Tianji a filter parameter.

filter过滤结果为仅包含某些属性的方法。默认不过滤。 

ReflectionMethod::IS_STATIC、 
ReflectionMethod::IS_PUBLIC、 
ReflectionMethod::IS_PROTECTED、 
ReflectionMethod::IS_PRIVATE、 
ReflectionMethod::IS_ABSTRACT、 
ReflectionMethod::IS_FINAL 的任意组合。

反射注释

注释信息,这里就以文档信息为例。

<?phprequire &#39;./bean/beans.php&#39;;
$protype = new ReflectionClass ( "Person" );
$properties = $protype->getProperties ();
// 反射获取到类的属性信息
foreach ( $properties as $property ) {    
echo $property . ":";    
$doc = $property->getDocComment ();    
echo "   " . $doc . "<br />";    e
cho "--------------------------------------------------------" . "<br />";
}$methods = $protype->getMethods();
foreach ($methods as $method) {    
echo $method->getName()."<br />";   
 $doc = $method->getDocComment ();    
 echo "   " . $doc . "<br />";    
 echo "--------------------------------------------------------" . "<br />";
}

Detailed code examples of PHP reflection technology (pictures and texts)

反射实例化

Detailed code examples of PHP reflection technology (pictures and texts)

<?phprequire &#39;./bean/beans.php&#39;;
$protype = new ReflectionClass ( "Person" );// 模拟数据库中获取到的值,以关联数组的形式抛出
$values = array(    "name"=>"郭璞",    "age"=> 21,    "address"=>"辽宁省大连市");// 开始实例化
$instance = $protype->newInstanceArgs($values);    
print_r($instance);// 
var_dump($instance);
echo $instance->getName();

Detailed code examples of PHP reflection technology (pictures and texts)

反射Grade类

<?phprequire &#39;./bean/beans.php&#39;;$classprotype = new ReflectionClass("Grade");$class = $classprotype->newInstanceArgs(array("name"=>"大三"));
var_dump($class);echo $class->getName();

Detailed code examples of PHP reflection technology (pictures and texts)

执行类的方法

$instance->getName(); 
// 执行Person 里的方法getName// 或者:
$method = $class->getmethod(&#39;getName&#39;); 
// 获取Person 类中的getName方法$method->invoke($instance);    
// 执行getName 方法// 或者:$method = $class->getmethod(&#39;setName&#39;); 
// 获取Person 类中的setName方法$method->invokeArgs($instance, array(&#39;snsgou.com&#39;));

总结

回顾一下,本次试验演示了PHP中的反射技术,对比分析了Java语言的反射技术的实现。也只能说各有利弊吧。

在Java中,反射技术是编写框架的基础。虽然在PHP中反射技术不是特别的重要,而且用的时候约束也比较多,稍显鸡肋。但是比葫芦画瓢的话,还是可以做出一些有用的小工具的。


The above is the detailed content of Detailed code examples of PHP reflection technology (pictures and texts). For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn