Как разрешить «Аргумент 1, переданный my_function (), должен быть экземпляром строки, строка, заданная« до PHP 7?

Вот мой код:

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

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

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

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

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

Резюме

Сообщение об ошибке запутывается по одной большой причине:

Имена примитивных типов не зарезервированы в 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 – примитивная строка? yes – строковый экземпляр? нет

$ s2 – примитивная строка? no – string instance? да

В PHP возможно, что string будет string за исключением случаев, когда она фактически является string . Как и на любом языке, использующем неявное преобразование типов, контекст – это все.

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

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

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

    Из руководства PHP :

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

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

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

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

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

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

    Предупреждение

    Псевдонимы для указанных выше скалярных типов не поддерживаются. Вместо этого они рассматриваются как имена классов или интерфейсов. Например, использование boolean как параметра или возвращаемого типа потребует аргумента или возвращаемого значения, которое является экземпляром класса или интерфейса boolean, а не типа 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 given»; поскольку в качестве типа аргумента допускаются только имена классов / интерфейсов, PHP пытается найти имя класса «строка», но не может найти его, потому что он является примитивным типом, поэтому с этой неудобной ошибкой терпит неудачу.

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

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

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

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

    Дополнительную информацию см. В руководстве по PHP .

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

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

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

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

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

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