【问题标题】:Awkward PHP type error in function arguments函数参数中出现尴尬的 PHP 类型错误
【发布时间】:2014-10-20 22:05:44
【问题描述】:

我已经定义了一个这样的函数:

   private function mediaExist(string $entry) { ...

我遇到了这种类型的错误:

   ... must be an instance of string, string given, called in ...

有什么帮助吗?

【问题讨论】:

  • 你不能用 PHP 做到这一点。这里 PHP 正在等待一个对象。 $entry 必须是字符串类型的对象。
  • 另外一点,如果你好奇,Hack 可以更好地检查Type-Hinting。我暂时不建议在生产服务器中使用它。 Hack 仍在开发中。
  • @Debflav:我认为您的意思是链接到 hack's type-annotations 文档,因为类型提示链接只是 PHP 的文档。对 OP:是的,hack 确实支持(很多)更严格的输入
  • 是的,这个更好。那是我想给的。第一个链接我没看就拿了。

标签: php types


【解决方案1】:

PHP 类型提示仅适用于类或数组:

function foo(array $bar, stdClass $object)
{//fine
}

但您不能键入提示原语/标量或资源类型:

function bar(int $num, string $str)
{}

这将调用自动加载器,它会尝试查找 intstring 类的类定义,这些类显然不存在。
这背后的理由很简单。 PHP 是一种松散类型的语言,数字字符串可以通过 type-juggling 转换为 int 或 float:

$foo = '123';
$bar = $foo*2;//foo's value is used as an int -> 123*2

引入类型提示是为了提高语言的 OO 功能:类/接口应该能够通过使用(除其他外)类型提示来强制执行合同。

如果要确保给定值是字符串,可以使用强制转换或类型检查函数:

function foo($string)
{
    $sureString = (string) $string;//cast to string
    if ($sureString != $string)
    {//loose comparison, if they are not equal, the argument could not be converted to a string reliable
        throw new InvalidArgumentException(__FUNCTION__.' expects a string argument, '.get_type($string).' given');
    }
}

资源而言(例如文件处理程序),修复起来同样容易:

function foobar(/* resource hint is not allowed */ $resource)
{
    if (!is_resource($resource))
    {
        throw new InvalidArgumentException(
            sprintf(
                '%s expects a resource, %s given',
                __FUNCTION__,
                get_type($resource)
            );
        );
    }
}

最后,在开发大型 PHP 项目时,最好的办法是使用 doc-blocks 和一个不错的 IDE。当您调用函数/方法时,IDE 将使用文档块告诉您预期的类型。确保满足这些标准是程序员的工作:

/**
 * Some documentation: what this function does, and how the arguments
 * are being used
 * @param array $data
 * @param string $key
 * @param string $errorMsg = ''
 * @return mixed
 * @throws InvalidArgumentException
 **/
function doStuff(array $data, $key, $errorMsg = '')
{
}

【讨论】:

  • 我不同意代码示例中的测试if ($sureString != $string) 您的条件不正确(太长,无法在评论中解释)。无论如何,很好的答案。
  • @Debflav:$sureString != $string 的优点是该检查将允许使用具有__toString 方法的对象。无论哪种方式:get_type() == 'string'is_string 和所有这些选项都同样有效。这一切都取决于具体情况。我本可以给出更全面的答案,但实际上,这一切都归结为我在前两句话中所说的:不允许原始类型提示,在函数/方法本身中使用检查并相应地处理错误
  • 我对整个答案很好(我已经赞成)。只是因为如果您有$string = 15;,您将不会进入这种状态。如果你想要一个字符串类型的值,我猜15 是有效的。
  • @Debflav:公平点......很可能15 不是一个有效的论点,但'15' 也不会是有效的。但仍然'15',作为查询结果集的一部分,应该用作int,但有时在技术上是字符串。这让我们又回到了同一个问题:如何检查,检查什么完全取决于具体情况
【解决方案2】:

如果你omit the string type constraint, it should work。 PHP 在尝试推断您传递给它的字符串文字的类型时遇到了麻烦,因此它假定无论它是什么,它都可能不是您要寻找的东西——恰好是 string

【讨论】:

    【解决方案3】:

    来自Type Hinting的文档

    类型提示不能用于标量类型,例如 int 或 string。也不允许使用资源和特征。

    这就是你得到错误的原因

    【讨论】:

      【解决方案4】:

      你可以这样查看

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-11-24
        • 2021-08-02
        • 2018-06-11
        • 2013-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多