Laravel框架原理(一)--Laravel中經常使用的PHP語法

一.後期靜態綁定

  自 PHP 5.3.0 起,PHP 增長了一個叫作後期靜態綁定的功能,用於在繼承範圍內引用靜態調用的類。用於在繼承範圍內引用靜態調用的類,即在類的繼承過程當中,使用的類再也不是當前類,而是調用的類。php

  下面介紹一個例子,具體原理和使用可參考 PHP手冊 中裏面詳細介紹後期靜態綁定。數組

Class A{
    public static function create(){
        $self = new self(); //所在位置的類的實例
        $static = new static(); //調用類的實例
        return array($self, $static);
    }
}
class B extends A{
}

$arr = B::create();
var_dump($arr[0]);
var_dump($arr[1]);

 輸出:閉包

object(A)#3 (0) {}
object(B)#4 (0) {}

 

與上述的輸出結果相同,在實例化對象中,static會根據運行時候調用的類來決定實例化的對象,而self是根據所在位置的類來決定實例化對象app

二.反射

  反射機制被多種語言普遍使用,主要用來動態獲取類、實例對象、方法等語言構建信息,經過API函數能夠實現對這些語言構建信息的動態獲取和動態操做等。下面展現一個使用反射的簡單例子。函數

Class ReflectionTest{
    public function call(){
        echo "hello world"."\r\n";
    }
}

$ref = new ReflectionClass('ReflectionTest');
$inst = $ref->newInstanceArgs();
$inst->call();

 上面的例子使用了ReflectionClass,使用ReflectionClass能夠獲取到類的基本信息,包含類的屬性、常量、方法、命名空間、以及對象的實例等等。例子中就是經過newInstanceArgs方法建立一個新的類實例。ReflectionClass類有如下方法:oop

      ReflectionClass::__construct — 初始化 ReflectionClass 類
      ReflectionClass::export — 導出一個類
      ReflectionClass::getConstant — 獲取定義過的一個常量
      ReflectionClass::getConstants — 獲取一組常量
      ReflectionClass::getConstructor — 獲取類的構造函數
      ReflectionClass::getDefaultProperties — 獲取默認屬性
      ReflectionClass::getDocComment — 獲取文檔註釋
      ReflectionClass::getEndLine — 獲取最後一行的行數
      ReflectionClass::getExtension — 根據已定義的類獲取所在擴展的 ReflectionExtension 對象
      ReflectionClass::getExtensionName — 獲取定義的類所在的擴展的名稱
      ReflectionClass::getFileName — 獲取定義類的文件名
      ReflectionClass::getInterfaceNames — 獲取接口(interface)名稱
      ReflectionClass::getInterfaces — 獲取接口
      ReflectionClass::getMethod — 獲取一個類方法的 ReflectionMethod。
      ReflectionClass::getMethods — 獲取方法的數組
      ReflectionClass::getModifiers — 獲取類的修飾符
      ReflectionClass::getName — 獲取類名
      ReflectionClass::getNamespaceName — 獲取命名空間的名稱
      ReflectionClass::getParentClass — 獲取父類
      ReflectionClass::getProperties — 獲取一組屬性
      ReflectionClass::getProperty — 獲取類的一個屬性的 ReflectionProperty
      ReflectionClass::getReflectionConstant — Gets a ReflectionClassConstant for a class's constant
      ReflectionClass::getReflectionConstants — Gets class constants
      ReflectionClass::getShortName — 獲取短名
      ReflectionClass::getStartLine — 獲取起始行號
      ReflectionClass::getStaticProperties — 獲取靜態(static)屬性
      ReflectionClass::getStaticPropertyValue — 獲取靜態(static)屬性的值
      ReflectionClass::getTraitAliases — 返回 trait 別名的一個數組
      ReflectionClass::getTraitNames — 返回這個類所使用 traits 的名稱的數組
      ReflectionClass::getTraits — 返回這個類所使用的 traits 數組
      ReflectionClass::hasConstant — 檢查常量是否已經定義
      ReflectionClass::hasMethod — 檢查方法是否已定義
      ReflectionClass::hasProperty — 檢查屬性是否已定義
      ReflectionClass::implementsInterface — 接口的實現
      ReflectionClass::inNamespace — 檢查是否位於命名空間中
      ReflectionClass::isAbstract — 檢查類是不是抽象類(abstract)
      ReflectionClass::isAnonymous — 檢查類是不是匿名類
      ReflectionClass::isCloneable — 返回了一個類是否可複製
      ReflectionClass::isFinal — 檢查類是否聲明爲 final
      ReflectionClass::isInstance — 檢查類的實例
      ReflectionClass::isInstantiable — 檢查類是否可實例化
      ReflectionClass::isInterface — 檢查類是不是一個接口(interface)
      ReflectionClass::isInternal — 檢查類是否由擴展或核心在內部定義
      ReflectionClass::isIterable — Check whether this class is iterable
      ReflectionClass::isIterateable — 檢查是否可迭代(iterateable)
      ReflectionClass::isSubclassOf — 檢查是否爲一個子類
      ReflectionClass::isTrait — 返回了是否爲一個 trait
      ReflectionClass::isUserDefined — 檢查是否由用戶定義的
      ReflectionClass::newInstance — 從指定的參數建立一個新的類實例
      ReflectionClass::newInstanceArgs — 從給出的參數建立一個新的類實例。
      ReflectionClass::newInstanceWithoutConstructor — 建立一個新的類實例而不調用它的構造函數
      ReflectionClass::setStaticPropertyValue — 設置靜態屬性的值
      ReflectionClass::__toString — 返回 ReflectionClass 對象字符串的表示形式。

 

三.trait

  相對於多繼承語言(如:C++),代碼複用問題對於單繼承語言(Ruby、PHP、JAVA/、C#)來講須要經過其餘方法解決,如Ruby中經過混入類解決。而PHP是經過Trait來實現代碼複用。this

<?php
Class Base{
    public function hello(){
        echo "Method hello from Base";
    }
}
trait A{
    public function hello(){
        echo "Method hello from A"."\r\n";
    }
    public function hi(){
        echo "Method Hi from A"."\r\n";
    }
    abstract public function abstractFun();
    static public function staticFun(){
        echo "A Static Method"."\r\n";
    }
    public function getValue(){
        static $value;
        $value++;
        echo $value."\r\n";
    }
}
trait B{
    public function hello(){
        parent::hello();
        echo "Method hello from B"."\r\n";
    }
    public function hi(){
        echo "Method Hi from B"."\r\n";
    }
}
trait AB{
    use A, B{
        B::hello insteadof A;
        A::hi insteadof B;
    }
}
Class Test extends Base{
    use AB;
    private $value = "value in Test"."\r\n";
    public function hi(){
        echo "Method Hi from Test"."\r\n";
    }
    public function abstractFun(){
        echo $this->value;
    }
}
$obj = new  Test();
$obj->hello();
$obj->hi();
$obj->staticFun();
$obj->abstractFun();

輸出:spa

<?php
Class Base{
    public function hello(){
        echo "Method hello from Base"."\r\n";
    }
}
trait A{
    public function hello(){
        echo "Method hello from A"."\r\n";
    }
    public function hi(){
        echo "Method Hi from A"."\r\n";
    }
    abstract public function abstractMethod();
    static public function staticMethod(){
        echo "A Static Method"."\r\n";
    }
    public function staticValue(){
        static $value;
        $value++;
        echo $value."\r\n";
    }
}
trait B{
    public function hello(){
        parent::hello();
        echo "Method hello from B"."\r\n";
    }
    public function hi(){
        echo "Method Hi from B"."\r\n";
    }
}
trait AB{
    use A, B{
        B::hello insteadof A;//解決名稱衝突
        A::hi insteadof B;
    }
}
Class Test extends Base{
    use AB;
    private $value = "value in Test"."\r\n";
    public function hi(){
        echo "Method Hi from Test"."\r\n";
    }
    public function abstractMethod(){
        echo $this->value;
    }
}
$obj = new  Test();
$obj->hello(); //輸出traitB中的hello方法
$obj->hi(); //輸出Test中的方法
$obj->staticMethod();//trait可定義static方法
$obj->abstractMethod();//trait可定義abstract方法
$obj->staticValue();//1
$obj->staticValue();//2   static可以使用static變量//1

輸出:.net

Method hello from Base
Method hello from B
Method Hi from Test
A Static Method
value in Test
1
2

  1.優先級:當前類優先級>trait>基類code

  2.多個trait組合:經過逗號分隔,使用use關鍵字列出多個trait

  3.衝突的解決:若是兩個trait都插入一個同名的方法,若沒明確解決衝突會產生一個致命錯誤。爲解決多個trait在同一個類中的命名衝突,需使用insteadof來指定使用衝突方法中的哪個;也能夠用as將其中一個衝突的方法以另外一個名稱引入。

    將上面例子中的 trait AB中使用insteadof的兩句刪除,會出現如下報錯

 Trait method hello has not been applied, because there are collisions with other trait methods on AB in D:XXXX.php on line 33

Fatal error: Trait method hello has not been applied, because there are collisions with other trait methods on AB in D:XXXX.php on line 33

  4.trait的抽象方法:在trait中使用抽象成員,是的類中必須實現這個抽象方法

  5.trait的靜態成員:在trait中能夠用靜態方法和靜態變量

  6.trait中的屬性定義:在trait中一樣能夠定義屬性

四.閉包函數

相關文章
相關標籤/搜索