silence - type hinting php
¿Cómo resolver "debe ser una instancia de cadena, cadena dada" antes de PHP 7? (9)
Aquí está mi código:
function phpwtf(string $s) {
echo "$s/n";
}
phpwtf("Type hinting is da bomb");
Lo que resulta en este error:
Error fatal detectable: el argumento 1 pasado a phpwtf () debe ser una instancia de cadena, cadena dada
Es más que un pequeño orwelliano ver a PHP reconocer y rechazar el tipo deseado en el mismo aliento. Hay cinco luces, maldita sea.
¿Cuál es el equivalente de la sugerencia de tipo para cadenas en PHP? Bonificación por la respuesta que explica exactamente lo que está sucediendo aquí.
A partir de PHP 7.0, las declaraciones de tipos permiten tipos escalares, por lo que estos tipos ahora están disponibles: self
, array
, callable
, bool
, float
, int
, string
. Los tres primeros estaban disponibles en PHP 5, pero los últimos cuatro son nuevos en PHP 7. Si utiliza cualquier otra cosa (por ejemplo, integer
o boolean
), se interpretará como un nombre de clase.
Antes de PHP 7, la sugerencia de tipo solo se puede utilizar para forzar los tipos de objetos y matrices. Los tipos escalares no son de tipo hintable. En este caso, se espera un objeto de la string
clase, pero le está dando una string
(escalar). El mensaje de error puede ser divertido, pero para empezar no se supone que funcione. Dado el sistema de escritura dinámica, esto en realidad tiene algún sentido pervertido.
Sólo puede "tipear manualmente " tipos de escalar:
function foo($string) {
if (!is_string($string)) {
trigger_error(''No, you fool!'');
return;
}
...
}
Como ya han dicho otros, la sugerencia de tipos actualmente solo funciona para tipos de objetos. Pero creo que el error particular que ha provocado podría estar en la preparación del próximo tipo de cadena SplString .
En teoría, se comporta como una cadena, pero como es un objeto, se pasaría la verificación del tipo de objeto. Desafortunadamente, aún no está en PHP 5.3, puede venir en 5.4, así que no lo he probado.
Creo que encasillado en php en el bloque interno, String en PHP no es un objeto como sé:
<?php
function phpwtf($s) {
$s = (string) $s;
echo "$s/n";
}
phpwtf("Type hinting is da bomb");
Del manual de PHP :
Las sugerencias de tipo solo pueden ser del tipo de objeto y matriz (desde PHP 5.1). No se admiten las sugerencias de tipo tradicional con int y cadena.
Así que lo tienes. El mensaje de error no es realmente útil, te lo digo.
** 2017 Edición **
PHP7 introdujo más declaraciones de tipo de datos de función, y el enlace mencionado anteriormente se ha movido a Argumentos de función: Declaraciones de tipo . Desde esa página:
Tipos validos
- Nombre de clase / interfaz : el parámetro debe ser una instancia de la clase o el nombre de interfaz dados. (desde PHP 5.0.0)
- self : el parámetro debe ser una instancia de la misma clase en la que se define el método. Esto solo se puede utilizar en los métodos de clase e instancia. (desde PHP 5.0.0)
- array : El parámetro debe ser un array. (desde PHP 5.1.0) callable El parámetro debe ser válido. PHP 5.4.0
- bool : el parámetro debe ser un valor booleano. (desde PHP 7.0.0)
- float : El parámetro debe ser un número de punto flotante. (desde PHP 7.0.0)
- int : el parámetro debe ser un entero (desde PHP 7.0.0)
- cadena : el parámetro debe ser una cadena. (desde PHP 7.0.0)
- iterable : El parámetro debe ser una matriz o una instancia de Traversable. (Desde PHP 7.1.0)
Advertencia
Los alias para los tipos escalares anteriores no son compatibles. En su lugar, se tratan como nombres de clase o interfaz. Por ejemplo, usar boolean como parámetro o tipo de retorno requerirá un argumento o valor de retorno que sea una instancia de la clase o interfaz booleana, en lugar de de tipo bool:
<?php function test(boolean $param) {} test(true); ?>
El ejemplo anterior dará como resultado:
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
La última advertencia es realmente significativa para comprender el error "El argumento debe ser del tipo cadena, cadena dada"; como la mayoría de los nombres de clase / interfaz solo están permitidos como tipo de argumento, PHP intenta localizar una "cadena" de nombre de clase, pero no puede encontrar ninguno porque es un tipo primitivo, por lo que falla con este error incómodo.
PHP permite "insinuar" cuando se proporciona una clase para especificar un objeto. Según el manual de PHP, "Las sugerencias de tipo solo pueden ser del tipo de objeto y matriz (desde PHP 5.1). Las sugerencias de tipo tradicional con int y cadena no son compatibles". El error es confuso debido a su elección de "cadena": coloque "myClass" en su lugar y el error se leerá de forma diferente: "El argumento 1 pasado a phpwtf () debe ser una instancia de myClass, cadena dada"
Recibí este error al invocar una función de un Controlador Laravel a un archivo PHP.
Después de un par de horas, encontré el problema: estaba usando $ esto desde una función estática.
Tal vez no sea seguro y bonito pero si debe:
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"));
(originalmente publicado por en su pregunta)
El mensaje de error es confuso por una gran razón:
Los nombres tipográficos primitivos no están reservados en PHP
Las siguientes son todas las declaraciones de clase válidas:
class string { }
class int { }
class float { }
class double { }
Mi error fue pensar que el mensaje de error se refería únicamente al tipo de cadena primitiva: la palabra ''instancia'' debería haberme dado pausa. Un ejemplo para ilustrar más a fondo:
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'')]);
Salida:
$ s1 - cadena primitiva? sí - ¿instancia de cadena? no
$ s2 - cadena primitiva? no - instancia de cadena? sí
En PHP es posible que una string
sea una string
excepto cuando en realidad es una string
. Al igual que con cualquier lenguaje que utiliza conversión de tipo implícita, el contexto lo es todo.