首页 文章

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

提问于
浏览
201

这是我的代码:

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

导致此错误:

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

看到PHP在同一口气中识别并拒绝所需的类型,这不仅仅是一点Orwellian . 该死的有五盏灯 .

PHP中字符串的类型提示相当于什么?奖励考虑答案,准确解释这里发生了什么 .

9 回答

  • 0

    在PHP 7之前type hinting只能用于强制对象和数组的类型 . 标量类型不是类型可约束的 . 在这种情况下,期望 string 类的对象,但是你给它一个(标量) string . 错误消息可能很有趣,但它不应该开始工作 . 鉴于动态类型系统,这实际上会产生某种变态感 .

    您只能手动"type hint"标量类型:

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

    来自PHP's manual

    类型提示只能是对象和数组(自PHP 5.1以来)类型 . 不支持使用int和string的传统类型提示 .

    所以你拥有它 . 错误消息并不是真的有用,但我告诉你 .

    ** 2017年编辑**

    PHP7引入了更多的函数数据类型声明,并且上述链接已移至Function arguments : Type declarations . 从那个页面:

    有效类型类/接口名称:参数必须是给定类或接口名称的实例 . (自PHP 5.0.0起)self:该参数必须是与定义方法的类相同的实例 . 这只能用于类和实例方法 . (自PHP 5.0.0起)数组:参数必须是数组 . (自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开始)可迭代:参数必须是数组或Traversable的instanceof . (自PHP 7.1.0起)警告不支持上述标量类型的别名 . 相反,它们被视为类或接口名称 . 例如,使用boolean作为参数或返回类型将需要一个参数或返回值,它是类或接口boolean的实例,而不是类型bool:<?php
    function test(boolean $ param){}
    测试(真);
    ?>
    上面的例子将输出:致命错误:未捕获TypeError:传递给test()的参数1必须是boolean的实例,给定布尔值,在第1行调用并在 - :1中定义

    最后一个警告实际上很重要,以理解错误“类型字符串的参数必须,字符串给出”;因为大多数只允许类/接口名称作为参数类型,PHP试图找到一个类名“string”,但找不到任何因为它是一个基本类型,因此失败了这个尴尬的错误 .

  • 0

    PHP允许“提示”提供指定对象的类 . 根据PHP手册,“类型提示只能是对象和数组(自PHP 5.1以来)类型 . 不支持使用int和string的传统类型提示 . ”错误令人困惑,因为您选择“字符串” - 将“myClass”放在其位置并且错误将以不同方式读取:“传递给phpwtf()的参数1必须是myClass的实例,字符串给出”

  • 19

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

    从理论上讲,它的行为类似于字符串,但由于它是一个对象,因此会传递对象类型验证 . 不幸的是它还没有在PHP 5.3中,可能会在5.4中出现,所以没有测试过 .

  • 3

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

    See the PHP manual for more information .

  • 8

    从Laravel Controller调用函数到PHP文件时出现此错误 .

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

  • 2

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

  • -1

    我认为对内部块上的php进行类型转换,PHP上的字符串不是对象,因为我知道:

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

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

    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"));
    

相关问题