键入提示标量类型数组和可调用项

在 PHP 5.1 中添加了关键字 array 的类型提示数组参数(以及 PHP 7.1 之后的返回值)的支持。任何维度和类型的任何数组以及空数组都是有效值。

在 PHP 5.4 中添加了对类型提示可调用的支持。is_callable() 对参数和返回值有效的任何值都暗示了 callable,即 Closure 对象,函数名字符串和 array(class_name|object, method_name)

如果函数名中出现拼写错误,使其不是 is_callable(),则会显示一条不太明显的错误消息:

致命错误:未捕获的 TypeError:传递给 foo() 的参数 1 必须是可调用的类型,给定的字符串/数组

function foo(callable $c) {}
foo("count"); // valid
foo("Phar::running"); // valid
foo(["Phar", "running"); // valid
foo([new ReflectionClass("stdClass"), "getName"]); // valid
foo(function() {}); // valid

foo("no_such_function"); // callable expected, string given

非静态方法也可以作为静态格式的 callable 传递,导致 PHP 7 和 5 中的弃用警告和级别 E_STRICT 错误。

方法可见性被考虑在内。如果使用 callable 参数的方法上下文无法访问所提供的可调用对象,则它最终会好像该方法不存在一样。

class Foo{
  private static function f(){
    echo "Good" . PHP_EOL;
  }

  public static function r(callable $c){
    $c();
  }
}

function r(callable $c){}

Foo::r(["Foo", "f"]);
r(["Foo", "f"]);

输出:

致命错误:未捕获 TypeError:传递给 r() 的参数 1 必须是可调用的,给定数组

在 PHP 7 中添加了对类型提示标量类型的支持。这意味着我们获得了对 booleans,integers,floats 和 strings 的类型提示支持。

<?php

function add(int $a, int $b) {
    return $a + $b;
}

var_dump(add(1, 2)); // Outputs "int(3)"

默认情况下,PHP 将尝试转换任何提供的参数以匹配其类型提示。更改对 add(1.5, 2) 的调用会产生完全相同的输出,因为浮动 1.5 由 PHP 转换为 int

要停止此行为,必须将 declare(strict_types=1); 添加到需要它的每个 PHP 源文件的顶部。

<?php

declare(strict_types=1);

function add(int $a, int $b) {
    return $a + $b;
}

var_dump(add(1.5, 2));

上面的脚本现在产生一个致命的错误:

致命错误:未捕获 TypeError:传递给 add() 的参数 1 必须是 integer 类型,float 给定

例外:特殊类型

某些 PHP 函数可能返回 resource 类型的值。由于这不是标量类型,而是特殊类型,因此无法键入提示。

举个例子,curl_init() 将返回 resource,以及 fopen()。当然,这两种资源彼此不兼容。因此,当明确键入提示 resource 时,PHP 7 将始终抛出以下 TypeError:

TypeError:传递给 sample() 的参数 1 必须是资源的实例,给定资源