成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

【modernPHP專(zhuān)題(2)】反射機(jī)制Reflection

mrli2016 / 3022人閱讀

摘要:簡(jiǎn)介是才有的新功能,它是用來(lái)導(dǎo)出或提取出關(guān)于類(lèi)方法屬性參數(shù)等的詳細(xì)信息,包括注釋。

簡(jiǎn)介

PHP Reflection API是PHP5才有的新功能,它是用來(lái)導(dǎo)出或提取出關(guān)于類(lèi)、方法、屬性、參數(shù)等的詳細(xì)信息,包括注釋。

class Reflection { } 
interface Reflector { }
class ReflectionException extends Exception { }
class ReflectionFunction implements Reflector { }
class ReflectionParameter implements Reflector { }
class ReflectionMethod extends ReflectionFunction { }
class ReflectionClass implements Reflector { }
class ReflectionObject extends ReflectionClass { }
class ReflectionProperty implements Reflector { }
class ReflectionExtension implements Reflector { } 

用得比較多的就只有兩個(gè)ReflectionClassReflectionObject,兩個(gè)的用法都一樣,只是前者針對(duì)類(lèi),后者針對(duì)對(duì)象,后者是繼承前者的類(lèi);然后其中又有一些屬性或方法能返回對(duì)應(yīng)的Reflection對(duì)象(ReflectionProperty以及ReflectionMethod)

ReflectionClass

具體參考手冊(cè):http://php.net/manual/zh/clas...

通過(guò)ReflectionClass,我們可以得到Person類(lèi)的以下信息:

常量 Contants

屬性 Property Names

方法 Method Names

靜態(tài)屬性 Static Properties

命名空間 Namespace

Person類(lèi)是否為final或者abstract

id;
  }

  public function setId($v){
    $this->id = $v;
  }

  public function getName(){
    return $this->name;
  }

  public function setName($v){
    $this->name = $v;
  }

  public function getBiography(){
    return $this->biography;
  }

  public function setBiography($v){
    $this->biography = $v;
  }
}

//傳遞類(lèi)名或?qū)ο筮M(jìn)來(lái)
$class = new ReflectionClass("appPerson");

//獲取屬性,不管該屬性是否public
$properties = $class->getProperties();
foreach($properties as $property) {
  echo $property->getName()."
";
}
// 輸出:
// _allowDynamicAttributes
// id
// name
// biography

//默認(rèn)情況下,ReflectionClass會(huì)獲取到所有的屬性,private 和 protected的也可以。如果只想獲取到private屬性,就要額外傳個(gè)參數(shù):
/*
 * ReflectionProperty::IS_STATIC
 * ReflectionProperty::IS_PUBLIC
 * ReflectionProperty::IS_PROTECTED
 * ReflectionProperty::IS_PRIVATE
 */
 
 //↓↓ 注意一個(gè)|組合: 獲得IS_PRIVATE或者IS_PROTECTED的屬性
$private_properties = $class->getProperties(ReflectionProperty::IS_PRIVATE|ReflectionProperty::IS_PROTECTED);

foreach($private_properties as $property) {
  //↓↓如果該屬性是受保護(hù)的屬性;
  if($property->isProtected()) {

    // ↓↓ 獲取注釋
    $docblock = $property->getDocComment();
    preg_match("/ type=([a-z_]*) /", $property->getDocComment(), $matches);
    echo $matches[1]."
";
  }
}
// Output:
// primary_autoincrement
// varchar
// text

$data = array("id" => 1, "name" => "Chris", "biography" => "I am am a PHP developer");
foreach($data as $key => $value) {
  if(!$class->hasProperty($key)) {
    throw new Exception($key." is not a valid property");
  }

  if(!$class->hasMethod("get".ucfirst($key))) {
    throw new Exception($key." is missing a getter");
  }

  if(!$class->hasMethod("set".ucfirst($key))) {
    throw new Exception($key." is missing a setter");
  }

  $object = new Person();

  // http://php.net/manual/zh/class.reflectionmethod.php
  // getMethod 獲得一個(gè)該方法的reflectionmethod對(duì)象,然后使用里面的invoke方法;
  $setter = $class->getMethod("set".ucfirst($key));
  $ok = $setter->invoke($object, $value);

  // Get the setter method and invoke it
  $getter = $class->getMethod("get".ucfirst($key));
  $objValue = $getter->invoke($object);

  // Now compare
  if($value == $objValue) {
    echo "Getter or Setter has modified the data.
";
  } else {
    echo "Getter and Setter does not modify the data.
";
  }
}
getMethod and invoke

ReflectionClass::getMethod — 獲取一個(gè)類(lèi)方法的 ReflectionMethod(可以理解為獲得這個(gè)類(lèi)方法的控制權(quán),不管這個(gè)類(lèi)方法是否是public)。

具體的參考:

http://php.net/manual/zh/clas...

http://php.net/manual/zh/refl...

 isPublic()){
  $reflectionMethod -> setAccessible(true);
}
/*
 * public mixed ReflectionMethod::invoke ( object $object [, mixed $parameter [, mixed $... ]] )
 * 1. 獲得某個(gè)類(lèi)方法的ReflectionMethod
 * 2. $object 該方法所在的類(lèi)實(shí)例的對(duì)象,然后第二參數(shù)起對(duì)號(hào)入座到該方法的每個(gè)參數(shù);
 * 3. 通過(guò)invoke就可以執(zhí)行這個(gè)方法了
 */
echo $reflectionMethod->invoke($obj, "GangGe","How","are you");

//也可以把參數(shù)作為數(shù)組傳進(jìn)來(lái)
echo $reflectionMethod -> invokeArgs($obj,array("GangGe","How","are you"));
getProperty

獲得一個(gè) ReflectionProperty 類(lèi)實(shí)例 (同上,獲得該屬性的控制權(quán)) http://cn2.php.net/manual/zh/...

getValue獲取屬性值
public mixed ReflectionProperty::getValue ([ object $object ] )

如果該獲得該實(shí)例的類(lèi)屬性不是一個(gè)static的屬性,就必須傳該類(lèi)的實(shí)例

getProperty("staticProperty")->getValue()); //靜態(tài)屬性可以不加參數(shù)
var_dump($reflectionClass->getProperty("property")->getValue(new Foo)); //非靜態(tài)屬性必須加傳一個(gè)類(lèi)實(shí)例
$reflectionProperty = $reflectionClass->getProperty("privateProperty"); //受保護(hù)的屬性就要通過(guò)setAccessible獲得其權(quán)限
$reflectionProperty->setAccessible(true);
var_dump($reflectionProperty->getValue(new Foo));
Example 模擬YII框架中控制器調(diào)用方法的實(shí)現(xiàn)
hasMethod($action)) {
    exit("Method $action does not existed!");
}
 
// 取類(lèi)的構(gòu)造函數(shù),返回的是ReflectionMethod對(duì)象
$constructor = $reflector->getConstructor();

// 取構(gòu)造函數(shù)的參數(shù),這是一個(gè)對(duì)象數(shù)組
$parameters = $constructor->getParameters();

// 遍歷參數(shù)
foreach ($parameters as $key => $parameter) {
    // 獲取參數(shù)聲明的類(lèi)
    $injector = new ReflectionClass($parameter->getClass()->name);
    // 實(shí)例化參數(shù)聲明類(lèi)并填入?yún)?shù)列表
    $parameters[$key] = $injector->newInstance(); //實(shí)例化$parameter->getClass()->name類(lèi)
}
 
// 使用參數(shù)列表實(shí)例 controller 類(lèi)
$instance = $reflector->newInstanceArgs($parameters);
// 執(zhí)行
$instance->$action();
 
class HelloController
{
    private $model;
 
    public function __construct(TestModel $model)
    {
        $this->model = $model;
    }
 
    public function actionWorld()
    {
        echo $this->model->property, PHP_EOL;
    }
}
 
class TestModel
{
    public $property = "property";
}
TP框架中實(shí)現(xiàn)前后控制器
isPublic()) {

    $class = new ReflectionClass("BlogAction");

    // 執(zhí)行前置方法
    if ($class->hasMethod("_before_detail")) {
        $beforeMethod = $class->getMethod("_before_detail");
        if ($beforeMethod->isPublic()) {
            $beforeMethod->invoke($instance);
        }
    }

    $method->invoke(new BlogAction);

    // 執(zhí)行后置方法
    if ($class->hasMethod("_after_detail")) {
        $beforeMethod = $class->getMethod("_after_detail");
        if ($beforeMethod->isPublic()) {
            $beforeMethod->invoke($instance);
        }
    }
}

// 執(zhí)行帶參數(shù)的方法
$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!";
}
其他參考
/**
 * 執(zhí)行App控制器
 */
public function execApp() {

    // 創(chuàng)建action控制器實(shí)例
    $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();

    // 獲取當(dāng)前操作名
    $action = ACTION_NAME;

    // 執(zhí)行當(dāng)前操作
    //call_user_func(array(&$controller, $action)); // 其實(shí)吧,用這個(gè)函數(shù)足夠啦?。?!
    try {
        $methodInfo = new ReflectionMethod($namespaceClassName, $action);
        if ($methodInfo->isPublic() && !$methodInfo->isStatic()) {
            $methodInfo->invoke($controller);
        } else { // 操作方法不是public類(lèi)型,拋出異常
            throw new ReflectionException();
        }
    } catch (ReflectionException $e) {
        // 方法調(diào)用發(fā)生異常后,引導(dǎo)到__call方法處理
        $methodInfo = new ReflectionMethod($namespaceClassName, "__call");
        $methodInfo->invokeArgs($controller, array($action, ""));
    }
    return;
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/31355.html

相關(guān)文章

  • modernPHP專(zhuān)題(3)】依賴(lài)注入與服務(wù)容器

    摘要:而依賴(lài)倒置原則的思想是,上層不應(yīng)該依賴(lài)下層,應(yīng)依賴(lài)接口。上面通過(guò)構(gòu)造函數(shù)注入對(duì)象的方式,就是最簡(jiǎn)單的依賴(lài)注入當(dāng)然注入不僅可以通過(guò)構(gòu)造函數(shù)注入,也可以通過(guò)屬性注入,上面你可以通過(guò)一個(gè)來(lái)動(dòng)態(tài)為這個(gè)屬性賦值。 依賴(lài)倒置和控制反轉(zhuǎn)是一種編程思想,而依賴(lài)注入就是通過(guò)服務(wù)容器實(shí)現(xiàn)這種面向接口或者是面向抽象編程的思想 概念理解 依賴(lài)倒置原則 依賴(lài)倒置是一種軟件設(shè)計(jì)思想,在傳統(tǒng)軟件中,上層代碼依賴(lài)于下...

    terro 評(píng)論0 收藏0
  • modernPHP專(zhuān)題(13)】ZendOpcache字節(jié)碼緩存

    摘要:概述字節(jié)碼緩存不是的新特性,有很多獨(dú)立的擴(kuò)展可以實(shí)現(xiàn),比如和等,但是截至目前這些擴(kuò)展都沒(méi)有集成到內(nèi)核,從開(kāi)始,內(nèi)置了字節(jié)碼緩存功能,名為。開(kāi)始之前,我們先來(lái)看看什么是字節(jié)碼緩存,以及字節(jié)碼緩存的作用是什么。該函數(shù)將重置整個(gè)字節(jié)碼緩存。 概述 字節(jié)碼緩存不是PHP的新特性,有很多獨(dú)立的擴(kuò)展可以實(shí)現(xiàn),比如APC、eAccelerator和Xache等,但是截至目前這些擴(kuò)展都沒(méi)有集成到PHP...

    KevinYan 評(píng)論0 收藏0
  • modernPHP專(zhuān)題(7)】生成器語(yǔ)法

    摘要:通過(guò)生成器來(lái)生成關(guān)聯(lián)數(shù)組下面每一行是用分號(hào)分割的字段組合,第一個(gè)字段將被用作鍵名。正常來(lái)說(shuō),產(chǎn)生的是一個(gè),它的成員變量與函數(shù)不存在別名引用關(guān)系。關(guān)鍵字在的版本,生成器允許從其他生成器,可迭代對(duì)象或數(shù)組通過(guò)關(guān)鍵字來(lái)生成對(duì)應(yīng)的值輸出 一般你在迭代一組數(shù)據(jù)的時(shí)候,需要?jiǎng)?chuàng)建一個(gè)數(shù)據(jù),假設(shè)數(shù)組很大,則會(huì)消耗很大性能,甚至造成內(nèi)存不足。 //Fatal error: Allowed memory ...

    jackwang 評(píng)論0 收藏0
  • modernPHP專(zhuān)題(6)】類(lèi)的延遲綁定(后期綁定)

    摘要:實(shí)例化對(duì)象里面的所在哪個(gè)類(lèi)就返回哪個(gè)類(lèi)。訪問(wèn)的是當(dāng)前類(lèi)有點(diǎn)像因?yàn)槠涫抢^承了的方法,而調(diào)用的。由此可見(jiàn),他們的區(qū)別只有在繼承中才能體現(xiàn)出來(lái),如果沒(méi)有任何繼承,那么這兩者是沒(méi)有區(qū)別的。但如果是在靜態(tài)方法內(nèi)本類(lèi)的話,最好還是用 以static::來(lái)調(diào)用,是在運(yùn)行的那個(gè)時(shí)刻才執(zhí)行綁定操作; 父類(lèi)中有個(gè)方法是延遲綁定的,在子類(lèi)::調(diào)用這個(gè)方法的時(shí)候它又回到調(diào)用的子類(lèi)開(kāi)始向上找; exampl...

    adam1q84 評(píng)論0 收藏0
  • modernPHP專(zhuān)題(11)】斷言ASSERT

    摘要:可以在任何時(shí)候啟用和禁用斷言驗(yàn)證,因此可以在測(cè)試時(shí)啟用斷言,而在部署時(shí)禁用斷言。會(huì)檢查指定的并在結(jié)果為時(shí)采取適當(dāng)?shù)男袆?dòng)視而定。中的斷言向后兼用并增強(qiáng)之前的的方法。它使得在生產(chǎn)環(huán)境中啟用斷言為零成本,并且提供當(dāng)斷言失敗時(shí)拋出特定異常的能力。 簡(jiǎn)述 編寫(xiě)代碼時(shí),我們總是會(huì)做出一些假設(shè),斷言就是用于在代碼中捕捉這些假設(shè),可以將斷言看作是異常處理的一種高級(jí)形式。程序員斷言在程序中的某個(gè)特定點(diǎn)該...

    WalkerXu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<