Как решить "должен быть экземпляр строки, заданной строки" до PHP 7?

Вот мой код:

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

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

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

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

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

Ответ 1

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

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

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

Ответ 2

Из руководства по 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)
  • строка: параметр должен быть строкой. (начиная с 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", но не может найти ни одного, потому что это примитивный тип, поэтому происходит сбой с этой неловкой ошибкой.

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

Подробнее см. руководство по PHP.

Ответ 6

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

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

Ответ 7

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

Ответ 8

Есть ли кто-то, кто действительно может помочь мне исправить это? Какой файл мне нужно исправить? Я в отчаянии!

Спасибо!

Ответ 9

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

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

Ответ 10

Возможно, это не безопасно и красиво, но если вы должны:

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