这是我的代码:
function phpwtf(string $s) {
echo "$s\n";
}
phpwtf("Type hinting is da bomb");
导致此错误:
可捕获的致命错误:传递给 phpwtf() 的参数 1 必须是字符串的实例,给定的字符串
看到 PHP 同时识别和拒绝所需的类型,这不仅仅是一点奥威尔式的。有五盏灯,该死的。
PHP中字符串的类型提示等价物是什么?对确切解释这里发生的事情的答案的额外考虑。
PHP 7 之前的type hinting 只能用于强制对象和数组的类型。标量类型不是类型提示的。在这种情况下,需要一个类 string
的对象,但您给它一个(标量)string
。错误消息可能很有趣,但它不应该一开始就起作用。鉴于动态类型系统,这实际上具有某种变态的意义。
您只能手动“输入提示”标量类型:
function foo($string) {
if (!is_string($string)) {
trigger_error('No, you fool!');
return;
}
...
}
从 PHP's manual:
类型提示只能是对象和数组(自 PHP 5.1 起)类型。不支持使用 int 和 string 进行的传统类型提示。
所以你有它。错误消息并没有真正的帮助,但我给了你。
** 2017 年编辑 **
PHP7 引入了更多函数数据类型声明,上述链接已移至 Function arguments : Type declarations。从那个页面:
有效类型
类/接口名称:参数必须是给定类或接口名称的实例。 (自 PHP 5.0.0 起)
self :参数必须是与定义该方法的类相同的类的实例。这只能用于类和实例方法。 (自 PHP 5.0.0 起)
array :参数必须是一个数组。 (自 PHP 5.1.0 起)
callable :参数必须是有效的可调用对象。 (自 PHP 5.4.0 起)
bool :参数必须是布尔值。 (自 PHP 7.0.0 起)
float :参数必须是浮点数。 (自 PHP 7.0.0 起)
int :参数必须是整数。 (自 PHP 7.0.0 起)
string :参数必须是字符串。 (自 PHP 7.0.0 起)
iterable :参数必须是一个数组或一个可遍历的实例。 (自 PHP 7.1.0 起)
警告 不支持上述标量类型的别名。相反,它们被视为类或接口名称。例如,使用 boolean 作为参数或返回类型将需要一个参数或返回值,它是类或接口 boolean 的实例,而不是 bool 类型:
上面的示例将输出:
致命错误:未捕获的类型错误:传递给 test() 的参数 1 必须是布尔值的实例,给定的布尔值,在第 1 行调用并在 -:1 中定义
最后一个警告实际上对于理解错误“Argument must of type string, string given”很重要;由于大多数情况下只允许类/接口名称作为参数类型,PHP 尝试定位类名“字符串”,但由于它是原始类型而找不到任何名称,因此失败并出现此尴尬错误。
PHP 允许“提示”,您可以在其中提供一个类来指定一个对象。根据 PHP 手册,“类型提示只能是对象和数组(自 PHP 5.1 起)类型。不支持使用 int 和字符串的传统类型提示。”由于您选择了“字符串”,因此该错误令人困惑 - 将“myClass”放在它的位置,错误将不同地读取:“传递给 phpwtf() 的参数 1 必须是 myClass 的实例,给定字符串”
正如其他人已经说过的,类型提示目前仅适用于对象类型。但我认为您触发的特定错误可能是在准备即将到来的字符串类型 SplString。
理论上它的行为就像一个字符串,但由于它是一个对象,所以它会通过对象类型验证。不幸的是,它还没有出现在 PHP 5.3 中,可能会出现在 5.4 中,所以还没有测试过。
从 PHP 7.0 开始,类型声明允许标量类型,因此这些类型现在可用:self
、array
、callable
、bool
、float
、int
、string
。前三个在 PHP 5 中可用,但后四个在 PHP 7 中是新的。如果您使用其他任何内容(例如 integer
或 boolean
)将被解释为类名。
See the PHP manual for more information。
也许不安全也不漂亮,但如果你必须:
class string
{
private $Text;
public function __construct($value)
{
$this->Text = $value;
}
public function __toString()
{
return $this->Text;
}
}
function Test123(string $s)
{
echo $s;
}
Test123(new string("Testing"));
new string(array(1,2,3))
从 Laravel 控制器调用函数到 PHP 文件时出现此错误。
几个小时后,我发现了问题:我在静态函数中使用了 $this。
Using $this when not in object context
确实是一条神秘的信息。
(最初由 leepowers 在他的问题中发布)
错误消息令人困惑的一个重要原因是:
PHP 中不保留原始类型名称
以下是所有有效的类声明:
class string { }
class int { }
class float { }
class double { }
我的错误在于认为错误消息仅指的是字符串原始类型——“实例”这个词应该让我停下来。一个进一步说明的例子:
class string { }
$n = 1234;
$s1 = (string)$n;
$s2 = new string();
$a = array('no', 'yes');
printf("\$s1 - primitive string? %s - string instance? %s\n",
$a[is_string($s1)], $a[is_a($s1, 'string')]);
printf("\$s2 - primitive string? %s - string instance? %s\n",
$a[is_string($s2)], $a[is_a($s2, 'string')]);
输出:
$s1 - 原始字符串?是 - 字符串实例?没有 $s2 - 原始字符串?否 - 字符串实例?是的
在 PHP 中,string
可能是 string
,除非它实际上是 string
。与任何使用隐式类型转换的语言一样,上下文就是一切。
我认为在块内部的 php 上进行类型转换,PHP 上的 String 不是我所知道的对象:
<?php
function phpwtf($s) {
$s = (string) $s;
echo "$s\n";
}
phpwtf("Type hinting is da bomb");
$s
是一个无法转换为字符串的对象(没有实现 __toString()
方法),(string) $s
可能会引发错误,所以它并不那么容易