这是我的代码:
function phpwtf(string $s) {
echo "$s\n";
}
phpwtf("Type hinting is da bomb");
导致此错误:
可捕获的致命错误:传递给phpwtf()的参数1必须是字符串的一个实例,字符串给定
看到PHP能够一口气识别并拒绝所需的类型,这不仅仅是一个Orwellian。该死的,有五个灯。
PHP中字符串的类型提示等效于什么?对答案的额外考虑,可以准确解释这里发生的情况。
这是我的代码:
function phpwtf(string $s) {
echo "$s\n";
}
phpwtf("Type hinting is da bomb");
导致此错误:
可捕获的致命错误:传递给phpwtf()的参数1必须是字符串的一个实例,字符串给定
看到PHP能够一口气识别并拒绝所需的类型,这不仅仅是一个Orwellian。该死的,有五个灯。
PHP中字符串的类型提示等效于什么?对答案的额外考虑,可以准确解释这里发生的情况。
Answers:
在PHP 7之前,类型提示只能用于强制对象和数组的类型。标量类型不是类型隐含的。在这种情况下,应该使用该类的对象string
,但是您要给它一个(标量)string
。该错误消息可能很有趣,但是一开始它不起作用。给定动态键入系统,这实际上具有某种变态的意义。
您只能手动 “键入提示”标量类型:
function foo($string) {
if (!is_string($string)) {
trigger_error('No, you fool!');
return;
}
...
}
从PHP的手册:
类型提示只能是对象和数组类型(自PHP 5.1起)。不支持使用int和string的传统类型提示。
这样就可以了。错误消息并没有真正的帮助,但是我给了你。
PHP7引入了更多的函数数据类型声明,并且前面提到的链接已移至Function参数:Type声明。从该页面:
有效类型
- 类/接口名称:参数必须是给定类或接口名称的实例。(自PHP 5.0.0起)
- self:参数必须是与定义方法的类相同的实例。这只能用于类和实例方法。(自PHP 5.0.0起)
- array:参数必须是一个数组。(自PHP 5.1.0起)callable该参数必须是有效的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:参数必须是Traversable的数组或实例。(自PHP 7.1.0起)
警告
不支持上述标量类型的别名。而是将它们视为类或接口名称。例如,使用布尔值作为参数或返回类型将需要一个作为类或接口布尔值的实例而不是布尔类型的实例的参数或返回值:
<?php function test(boolean $param) {} test(true); ?>
上面的示例将输出:
Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of boolean, boolean given, called in - on line 1 and defined in -:1
最后的警告实际上对于理解错误“字符串类型必须为字符串,给定字符串”很重要。因为大多数情况下只允许使用类/接口名称作为参数类型,所以PHP试图找到一个类名称“ string”,但由于它是原始类型而找不到任何名称,因此由于此尴尬错误而失败。
正如其他人已经说过的那样,类型提示当前仅适用于对象类型。但是我认为您触发的特定错误可能是在准备即将到来的字符串类型SplString时。
从理论上讲,它的行为类似于字符串,但是由于它是一个对象,因此将通过对象类型验证。不幸的是,它尚未在PHP 5.3中出现,可能会在5.4中出现,因此尚未对其进行测试。
随着PHP 7.0的类型声明允许标量类型,所以这些类型的,现在可供选择:self
,array
,callable
,bool
,float
,int
,string
。前三个在PHP 5中可用,但后四个在PHP 7中是新增功能。如果您使用其他任何内容(例如integer
或boolean
),则将其解释为类名。
(最初由leepowers在他的问题中发布)
错误消息令人困惑的原因有一个:
在PHP中不保留原始类型名称
以下是所有有效的类声明:
class string { }
class int { }
class float { }
class double { }
我的错误是认为错误消息仅是指字符串原始类型-“ instance”一词应该让我停顿一下。一个例子来进一步说明:
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中,可以将a string
设为string
例外,而实际上却是string
。与使用隐式类型转换的任何语言一样,上下文就是一切。
我认为在内部块上的php上进行类型转换,在PHP上的String并不是我所知道的对象:
<?php
function phpwtf($s) {
$s = (string) $s;
echo "$s\n";
}
phpwtf("Type hinting is da bomb");
(string) $s
如果$s
是无法转换为字符串的对象(可能未__toString()
实现任何方法),则可能会引发错误,所以它不那么容易