随着PHP8的发布,作为动态类型语言的PHP也有了更大的进步。
此处浅谈一下PHP8中的类型定义以及几个新特性
本文仅介绍重点,详细内容可以参考 PHP 官方。
数据类型 (Data Type)
数据类型 (Data Type) 用来表示储存的数据类型,也称为型别。
数据类型 | 说明 | 数据范例 |
---|
bool | 布尔 | true, false |
int | 整型 | 1, 0, -1, … |
float | 浮点数 | 0.1, -0.2, … |
string | 字符串 | “hello world!” |
array | 数组 | [“hello”, “world”, 2, 0.1] |
object | 对象 | new Example(), (object) [‘hello’ => ‘world’] |
resource | 资源 | 资源 |
null | 空值 | null |
Function
语法:(PHP7.0以上)
1 2 3 4
| function FUNCTION_NAME(VAR_TYPE $VAR_NAME = VAR_DEFAULT_VALUE, ...): RETURN_TYPE{ return $VAR; }
|
- FUNCTION_NAME:函数名
- VAR_TYPE: 自变量
- VAR_NAME: 自变量名称
- VAR_DEFAULT_VALUE: 自变量默认值,此自变量可以不被传入,不传入时自动采用默认值
- RETURN_TYPE: 返回值
- Nullsafe operator:加上 ? 表示可能会传 null
- 另外,可以使用 |null 或者现有的 ? 表示法来表示包含 nullable 的联合体。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function myStrValue(string|null $a = 'hello'): ?string { return $a; } echo myStrValue(); echo myStrValue(null); echo myStrValue('你好');
function myStrConcat(?string $a = 'hello', string $b = null): string { return $a . $b; } echo myStrConcat(); echo myStrConcat(null); echo myStrConcat(null, 'world'); echo myStrConcat('你好', '世界');
|
补充说明:
- PHP 属于动态类型程序语言,允许所有变量可以不用带入数据类型,改由系统自动判别。但动态类型程序语言最令人诟病的地方就是过度方便新手开发人员 (可以不理会类型),而苦了 Web Server (需要判别类型),也容易造成开发人员因为类型问题产生的语意BUG。
- 开发人员预先定义好数据类型,可以有效增加程序运行效率。PHP 7.0 起,允许在 function 内约束自变量类型、返回值类型。PHP8起,允许在 function 内约束复合类型。
范例
范例:没有任何自变量也不回传任何东西
1 2 3 4 5 6 7 8 9 10
|
function myFirstFunc(): void{ echo 'hellowrold'; return; }
myFirstFunc();
|
范例:两字符串相加,回传字符串类型,第二个自变量预设 null,表示可以不传入。
1 2 3 4 5 6 7 8 9 10 11 12
|
function myStrConcat(string $a, string $b = null): string{ return $a . $b; }
echo myStrConcat('hello', 'world'); echo myStrConcat('helloworld');
|
范例:通过数据库,可能会拿到 null,故返回值需检查 null。
1 2 3 4 5 6 7 8
|
function getUser(int $userId): ?object{ }
|
范例:复合类型,PHP8后允许自变量、返回值有复合类型。
1 2 3 4 5 6 7 8
|
function getUsers(int|array $userIds): ?array{ }
|
- 范例:
mixed = array|bool|callable|int|float|null|object|resource|string
(PHP中不写类型默认为mixed,例如:function getUsers($userId){}
。)- 请注意,mixed也可以用作参数或属性类型,而不仅仅是作为返回类型。
- 另请注意,由于mixed已包含null,因此不允许使其为空(nullable)。以下代码将触发错误:
1 2 3 4
| function getUsers(mixed $userId): ?mixed { }
|
其他
顺带提一下php8中比较喜欢的几个更新
Match表达式
你可以称它为switch表达式的大哥,match可以返回值,不需要break语句,可以组合条件,并且不执行任何类型的强制。
新的 match 类似于 switch,并具有以下功能:
- Match 是一个表达式,它可以储存到变量中亦可以直接返回。
- Match 分支仅支持单行,它不需要一个 break; 语句。
- Match 使用严格比较。
如下所示:1 2 3 4 5 6 7 8 9 10
| $result = match($input) { 0 => "hello", '1', '2', '3' => "world", }; $message = match ($statusCode) { 200, 300 => null, 404 => 'not found', 500 => 'server error', default => 'unknow status code' }
|
Throw表达式
throw 从语句更改为表达式,从而有可能在许多新位置引发异常:
1 2 3 4 5
| $callable = fn() => throw new Exception(); $triggerError = fn () => throw new MyError(); $foo = $bar['offset'] ?? throw new OffsetDoesNotExist('offset') $condition || throw new Exception('$condition must be truthy') && $condition2 || throw new Exception('$condition2 must be truthy');
|
用参数名传递参数而不是参数的顺序
1 2 3 4 5 6 7 8 9 10
| setcookie( name: 'test', expires: time() + 60 * 60 * 2 );
$data = [ 'name' => 'test', 'expires' => time() + 60 * 60 * 2 ]; setcookie(...$data);
|
构造器属性提升
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
class Point { public float $x; public float $y; public float $z; public function __construct( float $x = 0.0, float $y = 0.0, float $z = 0.0, ) { $this->x = $x; $this->y = $y; $this->z = $z; } }
class Point { public function __construct( public float $x = 0.0, public float $y = 0.0, public float $z = 0.0, ) {} }
|
字符串与数字的比较更符合逻辑
1 2 3 4 5 6 7 8
|
0 == 'foobar'
0 == 'foobar'
|
Nullsafe 运算符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
$country = null; if ($session !== null) { $user = $session->user; if ($user !== null) { $address = $user->getAddress(); if ($address !== null) { $country = $address->country; } } }
$country = $session?->user?->getAddress()?->country;
|
对象获取类名
1 2
| $object = new stdClass; var_dump($object::class);
|
static return type
1 2 3 4 5 6 7
| class Test { public function withWhatever($whatever): static { $clone = clone $this; $clone->whatever = $whatever; return $clone; } }
|