浅谈PHP8中的类型定义以及几个新特性

2023-12-11 20:52:36 浏览数 (1)

随着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以上)

代码语言:javascript复制
function FUNCTION_NAME(VAR_TYPE $VAR_NAME = VAR_DEFAULT_VALUE, ...): RETURN_TYPE{
  //do somethings
  return $VAR;
}

FUNCTION_NAME:函数名

VAR_TYPE: 自变量

VAR_NAME: 自变量名称

VAR_DEFAULT_VALUE: 自变量默认值,此自变量可以不被传入,不传入时自动采用默认值

RETURN_TYPE: 返回值

Nullsafe operator:加上 ? 表示可能会传 null

另外,可以使用 |null 或者现有的 ? 表示法来表示包含 nullable 的联合体。

代码语言:javascript复制
function myStrValue(string|null $a = 'hello'): ?string {
  return $a;
}
echo myStrValue();//hello
echo myStrValue(null);//
echo myStrValue('你好');//你好

function myStrConcat(?string $a = 'hello', string $b = null): string {//默认值为null亦可传null
  return $a . $b;
}
echo myStrConcat(); //hello
echo myStrConcat(null); //
echo myStrConcat(null, 'world'); //world
echo myStrConcat('你好', '世界'); //你好世界

补充说明:

  • PHP 属于动态类型程序语言,允许所有变量可以不用带入数据类型,改由系统自动判别。但动态类型程序语言最令人诟病的地方就是过度方便新手开发人员 (可以不理会类型),而苦了 Web Server (需要判别类型),也容易造成开发人员因为类型问题产生的语意BUG。
  • 开发人员预先定义好数据类型,可以有效增加程序运行效率。PHP 7.0 起,允许在 function 内约束自变量类型、返回值类型。PHP8起,允许在 function 内约束复合类型。

范例

范例:没有任何自变量也不回传任何东西

代码语言:javascript复制
/**
 * myFirstFunc
 * @return void
 */
function myFirstFunc(): void{
  echo 'hellowrold';
  return;  //回传 void 时,写 return 的话,后面不可以带返回值。也可以不写 return 
}

myFirstFunc();  // helloworld

范例:两字符串相加,回传字符串类型,第二个自变量预设 null,表示可以不传入。

代码语言:javascript复制
/**
 * my string concat
 * @param string $a string A
 * @param string $b string B
 * @return string
 */
function myStrConcat(string $a, string $b = null): string{
  return $a . $b;
}

echo myStrConcat('hello', 'world');  // helloworld
echo myStrConcat('helloworld');      // helloworld

范例:通过数据库,可能会拿到 null,故返回值需检查 null。

代码语言:javascript复制
/**
 * get user
 * @param int $userId user ID
 * @return object|null
 */
function getUser(int $userId): ?object{
  //do something
}

范例:复合类型,PHP8后允许自变量、返回值有复合类型。

代码语言:javascript复制
/**
 * getUsers
 * @param int|array $userIds user IDs
 * @return array|null
 */
function getUsers(int|array $userIds): ?array{
  //do something
}

范例:mixed = array|bool|callable|int|float|null|object|resource|string (PHP中不写类型默认为mixed,例如:function getUsers($userId){}。)

请注意,mixed也可以用作参数或属性类型,而不仅仅是作为返回类型。

另请注意,由于mixed已包含null,因此不允许使其为空(nullable)。以下代码将触发错误:

代码语言:javascript复制
// Fatal error: Mixed types cannot be nullable, null is already part of the mixed type.
function getUsers(mixed $userId): ?mixed {
  //do something
}

其他

顺带提一下php8中比较喜欢的几个更新

Match表达式

你可以称它为switch表达式的大哥,match可以返回值,不需要break语句,可以组合条件,并且不执行任何类型的强制。 新的 match 类似于 switch,并具有以下功能:

Match 是一个表达式,它可以储存到变量中亦可以直接返回。

Match 分支仅支持单行,它不需要一个 break; 语句。

Match 使用严格比较。 如下所示:

代码语言:javascript复制
$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 从语句更改为表达式,从而有可能在许多新位置引发异常:

代码语言:javascript复制
$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');

用参数名传递参数而不是参数的顺序

代码语言:javascript复制
setcookie(
  name: 'test',
  expires: time()   60 * 60 * 2
);

$data = [
  'name' => 'test',
  'expires' => time()   60 * 60 * 2
];
setcookie(...$data);

构造器属性提升

代码语言:javascript复制
/*
 * PHP7
 */
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;
  }
}
/*
 * PHP8
 */
class Point {
  public function __construct(
    public float $x = 0.0,
    public float $y = 0.0,
    public float $z = 0.0,
  ) {}
}

字符串与数字的比较更符合逻辑

代码语言:javascript复制
/*
 * PHP7
 */
0 == 'foobar' // true
/*
 * PHP8
 */
0 == 'foobar' // false

Nullsafe 运算符

代码语言:javascript复制
/*
 * PHP7
 */
$country =  null;
if ($session !== null) {
  $user = $session->user;
  if ($user !== null) {
    $address = $user->getAddress();
 
    if ($address !== null) {
      $country = $address->country;
    }
  }
}
/*
 * PHP8
 */
$country = $session?->user?->getAddress()?->country;

对象获取类名

代码语言:javascript复制
$object = new stdClass;
var_dump($object::class); // "stdClass"

static return type

代码语言:javascript复制
class Test {
    public function withWhatever($whatever): static {
        $clone = clone $this;
        $clone->whatever = $whatever;
        return $clone;
    }
}

0 人点赞