同福

PHP7的强类型语法的学习使用

介绍

介绍

PHP7强化了对象编程的语法,支持诸如:namespace、use等模块化的语法,支持强类型函数参数,支持强类型函数返回值

今天我们就来学习一下PHP7都有哪些变化

教程

php storm

使用php storm的小伙伴在编写PHP7语法的代码的时候会发现提示语法错误,我们需要按下 Alt + Shift + Enter 组合键开启PHP7的语法模式

namespace

命名空间

简单说就是给当前PHP文件里定义的对象或者函数分配一个住址

不同的命名空间下可以有相同名称的对象或者函数的定义,就好像北京可以有个小李明的小朋友,上海也可以有

格式

命名空间必须在PHP对象文件最前面定义,多级命名空间使用斜杠“\”分开

示例

我们定义 system.inc.php 这个对象文件里的命名空间为 TFAPI\system

system.inc.php

<?php

namespace TFAPI\system;

class system{

}

use

导入声明

通过namespace定义的对象或函数在使用的时候就必须通过use来指定具体的路径

因为不同的namespace下可以有相同名称的class或者function,所以我们要告诉当前使用这个对象的PHP文件我们使用哪个class或者function

格式

导入声明必须放在PHP对象文件的namespace之后定义,如果没有namespace就放在最前面定义

需要注意的是,namespace是精确到最后一级住址,use是要精确到最后一级住址下面的具体PHP对象文件的具体对象的

一般情况下,PHP对象文件里只有一个class定义,且class名称和PHP对象文件名称一致

示例

index.php

<?php

use TFAPI\system\system;

class index extends system{

}

自动加载

为了便于管理我们会通过 autoload 方式自动加载PHP对象文件

为了方便寻址我们设计模块对象的namespace的时候都是按照物理目录结构一一对应的

一个PHP对象文件里只有一个class定义,且class名称和文件名称一致,这样方便使用 autload 自动载入

autoload

我们给出一个 autoload 的代码,可以拿来放到自己的模块根目录用来给使用模块对象的PHP代码使用

autoload.php

define('TFAPI_ROOT_PATH', __DIR__ . '/');
define('TFAPI_FILE_EXTENSION', '.inc.php');

function TFAPI_Autoload(string $class):bool {
    $path = TFAPI_ROOT_PATH. str_replace("\\","/", substr($class, 6)). TFAPI_FILE_EXTENSION;
    if(file_exists($path)){
        include_once ($path);

        return true;
    }

    return false;
}

spl_autoload_register("TFAPI_Autoload");

示例

我们在 /data/web/TFAPI/Encoding/Encoding.inc.php 里定义了一个类 Encoding

然后把 autoload.php 放到 /data/web/TFAPI/ 下面

Encoding.inc.php

<?php

namespace TFAPI\Encoding;

class Encoding{

}

index.php

<?php

use TFAPI\Encoding\Encoding;

include ('/data/web/TFAPI/autoload.php');

class index{
    public index(){
        $myEncodingObj = new Encoding();
    }
}

这样就可以实现对象的自动载入了

变量类型

PHP7的变量类型包括基础类型、特殊类型、自定义类型(class)

基础类型

  • int:整型

  • float:浮点

  • bool:布尔

  • string:字符串

特殊类型

  • array:数组

  • function:函数

  • object:对象

自定义类型

自定义类型就是我们通过class定义的对象类型

继承类型

如果我们的对象继承了另一个对象的类型,使用这个对象初始化的实例也可以匹配另一个对象的类型

范式类型

object类型可以匹配所有内建对象和自定义对象类型,但是基础类型不能匹配,array也不能匹配

所以我们如果需要匹配任意类型的话,唯一的方法就是去掉类型限制,因为PHP本身就是弱类型的嘛

强类型

强类型函数参数是相对C++、JAVA、C#等语言说的

因为PHP是脚本语言,脚本语言是弱类型的语言

脚本语言的特点是解析一点执行一点,所以不需要检查整体完整性和严谨度

最明显的区别就是PHP如果在一个完全不会进入的流里面调用一个不存在的对象是不会报错的,但是在JAVA里就不行了,编译都过不去

强类型函数参数

强类型函数参数就是要限制函数参数的类型必须为指定类型,否则会报异常错误

注意事项

  • 指定了类型之后传入的参数就必须是这个类型的,否则就会报错,传入 null 也不行

  • 毕竟无法保证参数一定是有效的,所以如果需要兼容 null 就需要在传入参数类型的前面增加“?”标记

  • 如果需要兼容范式类型参数,就请去掉类型限制好了,没有别的办法

强类型函数返回值

强类型函数返回值就是要限制函数返回值的类型必须是指定类型,否则会报异常错误

注意事项

  • 指定了类型之后函数返回值就必须是这个类型的,否则就会报错,返回 null 也不行

  • 同样的如果需要兼容 null 就需要在函数返回值类型的前面增加“?”标记

  • 同样的如果需要兼容范式类型函数返回值,就请去掉类型限制吧

  • 如果函数没有返回值,就指定类型为 void 类型

实践

实践出真知,我们来实际地用一用PHP7的强类型语法吧

示例

我们做了一个测试脚本,包括了比较全面的示例情况

<?php

namespace TFAPI\Tests;

class myData{
    public string $key;
    public string $value;
}

class myDataSon extends myData{

}

class myClass{
    public array $items;
    public myData $dataObj;
    public ?myDataSon $dataSonObj;

    /**
     * @param string $key
     * @param mixed $value
     */
    public function set(string $key, $value):void {
        $this->items[$key] = $value;
    }

    /**
     * @param string $key
     * @return mixed
     */
    public function get(string $key) {
        return $this->items[$key];
    }

    public function setData(myData $obj):void {
        $this->dataObj = $obj;
    }

    public function getData():myData {
        return $this->dataObj;
    }

    public function setDataSon(?myDataSon $obj):void {
        if($obj != null){
            $this->dataSonObj = $obj;
        }
    }

    public function getDataSon():?myDataSon {
        return $this->dataSonObj;
    }
}

$myClassObj = new myClass();

// 因为是范式(无类型)所以传什么都行
$myClassObj->set("int", 123);

// 传字符串也行
$myClassObj->set("string", "str");

// 传数组也行
$myClassObj->set("array", array());

// 因为指定了 myData 类型,传其他的就不行了,null 也不行
$myClassObj->setData(new myData());

// 因为指定了 myDataSon 类型,传其他的就不行了
$myClassObj->setDataSon(new myDataSon());

// 但是因为有“?”标记,所以可以传 null 进来
$myClassObj->setDataSon(null);

var_dump($myClassObj->get("int"));
var_dump($myClassObj->get("string"));
var_dump($myClassObj->get("array"));
var_dump($myClassObj->getData());
var_dump($myClassObj->getDataSon());

版本差异

PHP7

  • 可以指定函数的参数类型

  • 可以指定函数返回值的类型

PHP7.3

  • 可以兼容继承类的类型匹配,即子类实例可以匹配父类要求的场景

PHP7.4

  • 可以指定对象属性的类型

总结

使用强类型语法之后,可以让我们的代码更严谨,代码更可靠,并且依靠PHP7的全新引擎保证执行速度基本不受影响