• 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"."
    ";
        }
    }
    
    $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"."
    ";
        }
        public function hi(){
            echo "Method Hi from A"."
    ";
        }
        abstract public function abstractFun();
        static public function staticFun(){
            echo "A Static Method"."
    ";
        }
        public function getValue(){
            static $value;
            $value++;
            echo $value."
    ";
        }
    }
    trait B{
        public function hello(){
            parent::hello();
            echo "Method hello from B"."
    ";
        }
        public function hi(){
            echo "Method Hi from B"."
    ";
        }
    }
    trait AB{
        use A, B{
            B::hello insteadof A;
            A::hi insteadof B;
        }
    }
    Class Test extends Base{
        use AB;
        private $value = "value in Test"."
    ";
        public function hi(){
            echo "Method Hi from Test"."
    ";
        }
        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"."
    ";
        }
    }
    trait A{
        public function hello(){
            echo "Method hello from A"."
    ";
        }
        public function hi(){
            echo "Method Hi from A"."
    ";
        }
        abstract public function abstractMethod();
        static public function staticMethod(){
            echo "A Static Method"."
    ";
        }
        public function staticValue(){
            static $value;
            $value++;
            echo $value."
    ";
        }
    }
    trait B{
        public function hello(){
            parent::hello();
            echo "Method hello from B"."
    ";
        }
        public function hi(){
            echo "Method Hi from B"."
    ";
        }
    }
    trait AB{
        use A, B{
            B::hello insteadof A;//解决名称冲突
            A::hi insteadof B;
        }
    }
    Class Test extends Base{
        use AB;
        private $value = "value in Test"."
    ";
        public function hi(){
            echo "Method Hi from Test"."
    ";
        }
        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中同样可以定义属性

    四.闭包函数

  • 相关阅读:
    Shell命令之文本操作
    乘法表
    万年历
    猜数游戏
    Linux下如何进行FTP安装与设置
    CentOS 安装nload(流量统计)
    linux下创建用户并且限定用户主目录
    ftp 解决不能上传问题
    【题解】[TJOI2018]数学计算
    【平衡树做题记录】
  • 原文地址:https://www.cnblogs.com/slothccc/p/11671453.html
Copyright © 2020-2023  润新知