Laravel框架原理(一)--Laravel中常用的PHP语法

一.后期静态绑定

  自 PHP 5.3.0 起,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是根据所在位置的类来决定实例化对象

二.反射

  反射机制被多种语言广泛使用,主要用来动态获取类、实例对象、方法等语言构建信息,通过API函数可以实现对这些语言构建信息的动态获取和动态操作等。下面展示一个使用反射的简单例子。

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

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

 上面的例子使用了ReflectionClass,使用ReflectionClass可以获取到类的基本信息,包含类的属性、常量、方法、命名空间、以及对象的实例等等。例子中就是通过newInstanceArgs方法创建一个新的类实例。ReflectionClass类有以下方法:

      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来实现代码复用。

<?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();

输出:

<?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

输出:

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

  1.优先级:当前类优先级>trait>基类

  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中同样可以定义属性

四.闭包函数

posted @ 2019-10-14 14:49  sloth_ccc  阅读(474)  评论(0编辑  收藏  举报