ChatGPT解决这个技术问题 Extra ChatGPT

如何在 PHP 7 之前解决“必须是字符串的实例,给定的字符串”?

这是我的代码:

function phpwtf(string $s) {
    echo "$s\n";
}
phpwtf("Type hinting is da bomb");

导致此错误:

可捕获的致命错误:传递给 phpwtf() 的参数 1 必须是字符串的实例,给定的字符串

看到 PHP 同时识别和拒绝所需的类型,这不仅仅是一点奥威尔式的。有五盏灯,该死的。

PHP中字符串的类型提示等价物是什么?对确切解释这里发生的事情的答案的额外考虑。

好吧,那是因为你做错了。首先,您的代码不应该工作。阅读 PHP 文档中的类型杂耍。 PHP 是动态类型和弱类型。您可以使用 (string) 将参数转换为字符串(尽管仅在函数体中),但您只能像在代码片段中那样提示对象和数组。
@Gordon,我在 5.6 上测试过。仍然没有运气。
@Pacerier 请关注 wiki.php.net/rfc 了解最新动态。
显然,根据 source,标量类型提示(正如 OP 直观预期的那样)终于在 PHP *7* 的 RFC 下获得批准。已获批准的 RFC 显然还提供 syntactic sugar 用于类型检查 return-values 以及参数(参数)。即将到来的时间已经很长了。

M
Madbreaks

PHP 7 之前的type hinting 只能用于强制对象和数组的类型。标量类型不是类型提示的。在这种情况下,需要一个类 string 的对象,但您给它一个(标量)string。错误消息可能很有趣,但它不应该一开始就起作用。鉴于动态类型系统,这实际上具有某种变态的意义。

您只能手动“输入提示”标量类型:

function foo($string) {
    if (!is_string($string)) {
        trigger_error('No, you fool!');
        return;
    }
    ...
}

@deceze,是否有反向类型提示的语法?例如,除了数组之外的任何东西。
@Pacerier 不,没有。
此答案对 PHP 7 无效
T
TylerH

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 尝试定位类名“字符串”,但由于它是原始类型而找不到任何名称,因此失败并出现此尴尬错误。


S
Surreal Dreams

PHP 允许“提示”,您可以在其中提供一个类来指定一个对象。根据 PHP 手册,“类型提示只能是对象和数组(自 PHP 5.1 起)类型。不支持使用 int 和字符串的传统类型提示。”由于您选择了“字符串”,因此该错误令人困惑 - 将“myClass”放在它的位置,错误将不同地读取:“传递给 phpwtf() 的参数 1 必须是 myClass 的实例,给定字符串”


m
mario

正如其他人已经说过的,类型提示目前仅适用于对象类型。但我认为您触发的特定错误可能是在准备即将到来的字符串类型 SplString

理论上它的行为就像一个字符串,但由于它是一个对象,所以它会通过对象类型验证。不幸的是,它还没有出现在 PHP 5.3 中,可能会出现在 5.4 中,所以还没有测试过。


T
TwoStraws

从 PHP 7.0 开始,类型声明允许标量类型,因此这些类型现在可用:selfarraycallableboolfloatintstring。前三个在 PHP 5 中可用,但后四个在 PHP 7 中是新的。如果您使用其他任何内容(例如 integerboolean)将被解释为类名。

See the PHP manual for more information


P
Patrick

也许不安全也不漂亮,但如果你必须:

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))
e
ecairol

从 Laravel 控制器调用函数到 PHP 文件时出现此错误。

几个小时后,我发现了问题:我在静态函数中使用了 $this。


Using $this when not in object context 确实是一条神秘的信息。
u
user719662

(最初由 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。与任何使用隐式类型转换的语言一样,上下文就是一切。


s
subosito

我认为在块内部的 php 上进行类型转换,PHP 上的 String 不是我所知道的对象:

<?php
function phpwtf($s) {
    $s = (string) $s;
    echo "$s\n";
}
phpwtf("Type hinting is da bomb");

您可以在函数内添加 is_string() 验证,以防止将其他值传递给函数。
如果 $s 是一个无法转换为字符串的对象(没有实现 __toString() 方法),(string) $s 可能会引发错误,所以它并不那么容易
是的,亚尼克,你是对的。但是我们不能强制所有输入都是字符串,对吧?这就是为什么例外来玩。我们可以结合各种验证并捕获其余部分的异常;)
我只是说应该避免在不首先检查变量是否可以转换的情况下将一些变量转换为字符串,主要是因为捕获异常的成本很高,并且会导致不良的设计模式/编码习惯。

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅