Как решить "должен быть экземпляр строки, заданной строки" до PHP 7? - PullRequest
205 голосов
/ 05 ноября 2010

Вот мой код:

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

Что приводит к этой ошибке:

Исправляемая фатальная ошибка: аргумент 1, передаваемый в phpwtf (), должен быть экземпляром строки, в которой задана строка

Это больше, чем маленький оруэлловец, видеть, как PHP распознает и отклоняет желаемый тип на одном дыхании. Черт возьми, пять огней.

Что эквивалентно типу хинтинга для строк в PHP? Бонус за рассмотрение ответа, который точно объясняет, что здесь происходит.

Ответы [ 9 ]

188 голосов
/ 05 ноября 2010

До PHP 7 подсказка типа может использоваться только для принудительного использования типов объектов и массивов.Скалярные типы не являются Hintable.В этом случае ожидается объект класса string, но вы даете ему (скаляр) string.Сообщение об ошибке может быть забавным, но оно не должно работать с самого начала.Учитывая динамическую систему ввода, это на самом деле имеет какой-то извращенный смысл.

Вы можете только вручную скалярные типы "подсказка типа":

function foo($string) {
    if (!is_string($string)) {
        trigger_error('No, you fool!');
        return;
    }
    ...
}
20 голосов
/ 05 ноября 2010

С Руководство по PHP :

Тип Подсказки могут быть только типа объекта и массива (начиная с PHP 5.1). Подсказка традиционного типа с использованием int и string не поддерживается.

Итак, у вас есть. Сообщение об ошибке не очень полезно, хотя я даю вам это.

** 2017 Редактировать **

PHP7 представил больше объявлений типов данных функций, и вышеупомянутая ссылка была перемещена в Аргументы функций: объявления типов . С этой страницы:

Допустимые типы

  • Имя класса / интерфейса : Параметр должен быть экземпляром данного класса или имени интерфейса. (начиная с PHP 5.0.0)
  • self : Параметр должен быть экземпляром того же класса, что и класс, для которого определен метод. Это можно использовать только для методов класса и экземпляра. (начиная с PHP 5.0.0)
  • массив : параметр должен быть массивом. (начиная с 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 : Параметр должен быть либо массивом, либо экземпляром Traversable. (начиная с PHP 7.1.0)

Внимание

Псевдонимы для указанных выше скалярных типов не поддерживаются. Вместо этого они рассматриваются как имена классов или интерфейсов. Например, для использования логического значения в качестве параметра или возвращаемого типа потребуется аргумент или возвращаемое значение, которое является экземпляром класса или интерфейса логического типа, а не типа bool:

<?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

Последнее предупреждение действительно важно для понимания ошибки "Аргумент должен иметь тип string, string string"; поскольку в качестве типа аргумента в основном разрешены только имена классов / интерфейсов, PHP пытается найти имя класса «string», но не может найти ни одного, потому что это примитивный тип, поэтому происходит сбой с этой неловкой ошибкой.

8 голосов
/ 05 ноября 2010

PHP позволяет «подсказку», где вы указываете класс для указания объекта.Согласно руководству по PHP, «Типовые подсказки могут иметь только тип объекта и массива (начиная с PHP 5.1). Традиционный тип подсказок с помощью int и string не поддерживается».Ошибка сбивает с толку из-за того, что вы выбрали «string» - поставьте «myClass» на место, и ошибка будет выглядеть по-другому: «Аргумент 1, переданный phpwtf (), должен быть экземпляром myClass, строка, указанная»

3 голосов
/ 05 ноября 2010

Как уже говорили другие, подсказки типов в настоящее время работают только для типов объектов.Но я думаю, что конкретная ошибка, которую вы вызвали, может быть связана с подготовкой следующего типа строки SplString .

Теоретически он ведет себя как строка, но, поскольку это объект, он будет передаватьпроверка типа объекта.К сожалению, это еще не в PHP 5.3, может появиться в 5.4, поэтому не проверял это.

2 голосов
/ 28 апреля 2016

Начиная с PHP 7.0, объявления типов допускают скалярные типы, поэтому теперь доступны следующие типы: self, array, callable, bool, float, int, string. Первые три были доступны в PHP 5, но последние четыре являются новыми в PHP 7. Если вы используете что-либо еще (например, integer или boolean), это будет интерпретироваться как имя класса.

Для получения дополнительной информации см. Руководство по PHP * .

0 голосов
/ 04 июня 2018

(первоначально опубликовано 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. Как и в любом языке, использующем неявное преобразование типов, контекст - это все.

0 голосов
/ 18 марта 2016

Я получил эту ошибку при вызове функции из контроллера Laravel в файл PHP.

Через пару часов я обнаружил проблему: я использовал $ this изнутристатическая функция.

0 голосов
/ 14 июля 2011

Может быть, небезопасно и красиво, но если вам нужно:

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"));
0 голосов
/ 05 ноября 2010

Я думаю, что приведение типов на php внутри блока, String на PHP не объект, как я знаю:

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