如何使用反射來分析PHP的數據結構

更準備的說是 如何用PHP分析類內部的結構。php

介紹

當我開始學習PHP編程時,可能並不知道 Reflection API 的強大功能,主要緣由是我不須要它來設計個人類,模塊甚至是包等等,可是它在不少地方都有很是不錯的能力。laravel

下面咱們來介紹 Reflection API,主要是從這幾個方面git

  1. 什麼是Reflection API?
  2. 安裝和配置
  3. 使用
  4. 總結

什麼是 Reflection API

Reflection 是計算機程序在運行時檢查,修改本身的結構和行爲的能力 - 維基百科github

這是什麼意思呢?讓咱們來看下面的代碼片斷:編程

/**
 * Class Profile
 */
class Profile
{
   /**
    * @return string
    */
   public function getUserName(): string
   {
      return 'Foo';
   }
}

如今,Profile類是一個使用 ReflectionClass 的黑盒子,你能夠獲取它裏面的內容:api

// instantiation
$reflectionClass = new ReflectionClass('Profile');

// get class name
var_dump($reflectionClass->getName());
=> output: string(7) "Profile"

// get class documentation
var_dump($reflectionClass->getDocComment());
=> output:
string(24) "/**
 * Class Profile
 */"

所以,ReflectionClass 就像咱們Profile類的分析師,這是 Reflection API 的主要思想。函數

除了上面用到的,其實還有更多,以下:單元測試

ReflectionClass:報告一個類的信息。 ReflectionFunction:報告有關函數的信息。 ReflectionParameter:檢索有關函數或方法參數的信息。 ReflectionClassConstant:報告關於類常量的信息。學習

更多文檔能夠看這裏 反射測試

安裝和配置

Reflection API 是PHP內置的,不須要安裝或配置,它已是核心的一部分。

使用

在這裏,咱們經過更多,來看如何使用 Reflection API:

例一:獲取特定類的父類

// here we have the child class
class Child extends Profile
{
}

$class = new ReflectionClass('Child');

// here we get the list of all parents
print_r($class->getParentClass()); // ['Profile']

例二:獲取 getUserName() 函數註釋

$method = new ReflectionMethod('Profile', 'getUserName');
var_dump($method->getDocComment());
=> output:
string(33) "/**
 * @return string
 */"

例三:它能夠像 instanceofis_a() 同樣來驗證對象:

$class = new ReflectionClass('Profile');
$obj   = new Profile();

var_dump($class->isInstance($obj)); // bool(true)

// same like
var_dump(is_a($obj, 'Profile')); // bool(true)

// same like
var_dump($obj instanceof Profile); // bool(true)

例子四:在某些狀況下,你會發現本身停留在單元測試中,想知道如何測試私有函數?!

// add getName() scope as private
private function getName(): string
{
    return 'Foo';
}

$method = new ReflectionMethod('Profile', 'getUserName');
// check if it is private so we set it as accessible
if ($method->isPrivate()) {
    $method->setAccessible(true);
}

echo $method->invoke(new Profile()); // Foo

前面的例子很是簡單,下面是一些能夠普遍查找Reflection API的地方:

  • 文檔生成器:laravel-apidoc-generator軟件包,它普遍使用ReflectionClassReflectionMethod 來獲取關於類和方法的信息,而後處理它們,檢出這個代碼塊。

  • 依賴注入容器:下一篇來看。

結論

PHP提供了一個豐富的反射API,使咱們能夠更容易到達OOP結構的任何區域。

說白了就是在PHP運行時,能夠經過反射深刻到類的內部,作咱們想作的事情。

關於更多PHP知識,能夠前往 PHPCasts

相關文章
相關標籤/搜索