web-dev-qa-db-fra.com

Comment résoudre "doit être une instance de chaîne, chaîne donnée" avant PHP 7?

Voici mon code:

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

Ce qui entraîne cette erreur:

Erreur fatale capturable: l'argument 1 transmis à phpwtf () doit être une instance de chaîne, chaîne donnée

C’est plus qu’un petit Orwellien de voir PHP reconnaître et rejeter le type souhaité dans le même souffle. Il y a cinq lumières, bon sang.

Quel est l'équivalent de l'indicateur de type pour les chaînes en PHP? Considération supplémentaire sur la réponse qui explique exactement ce qui se passe ici.

203
leepowers

Avant PHP 7 l'indication de type ne peut être utilisée que pour forcer les types d'objets et de tableaux. Les types scalaires ne peuvent pas être renseignés. Dans ce cas, un objet de la classe string est attendu, mais vous lui attribuez une valeur (scalaire) string. Le message d'erreur peut être drôle, mais il n'est pas censé fonctionner pour commencer. Compte tenu du système de typage dynamique, cela a en fait un sens pervers.

Vous pouvez uniquement manuellement "taper un indice" types scalaires:

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

De Manuel PHP :

Les astuces de type ne peuvent être que de type objet et tableau (depuis PHP 5.1). Les conseils de type traditionnels avec int et string ne sont pas pris en charge.

Donc vous l'avez. Le message d'erreur n'est pas vraiment utile, je vous le donne cependant.

** 2017 Éditer **

PHP7 a introduit plus de déclarations de types de données de fonctions et le lien susmentionné a été déplacé vers Arguments de la fonction: Déclarations de types . De cette page:

Types valides

  • Nom de classe/interface: le paramètre doit être une instance du nom de classe ou d'interface donné. (depuis PHP 5.0.0)
  • self: le paramètre doit être une instance de la même classe que celle sur laquelle la méthode est définie. Ceci ne peut être utilisé que sur des méthodes de classe et d'instance. (depuis PHP 5.0.0)
  • array: le paramètre doit être un tableau. (depuis PHP 5.1.0) callable Le paramètre doit être un callable valide. PHP 5.4.0
  • bool: le paramètre doit être une valeur booléenne. (depuis PHP 7.0.0)
  • float: le paramètre doit être un nombre à virgule flottante. (depuis PHP 7.0.0)
  • int: le paramètre doit être un entier. (depuis PHP 7.0.0)
  • string: le paramètre doit être une chaîne. (depuis PHP 7.0.0)
  • iterable: le paramètre doit être un tableau ou une instance de Traversable. (depuis PHP 7.1.0)

Attention

Les alias pour les types scalaires ci-dessus ne sont pas pris en charge. Au lieu de cela, ils sont traités comme des noms de classe ou d'interface. Par exemple, utiliser boolean en tant que paramètre ou type de retour nécessitera un argument ou une valeur de retour qui est une instance de la classe ou de l'interface boolean, plutôt que du type bool:

<?php
   function test(boolean $param) {}
   test(true);
 ?>

L'exemple ci-dessus affichera:

 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

Le dernier avertissement est réellement significatif pour comprendre l’erreur "Argument doit être de type chaîne, chaîne donnée"; comme la plupart du temps, seuls les noms de classe/interface sont autorisés en tant que type d'argument, PHP essaie de localiser un nom de classe "string", mais n'en trouve aucun car il s'agit d'un type primitif.

19
Yanick Rochon

PHP permet "d'indices" lorsque vous fournissez une classe pour spécifier un objet. Selon le manuel PHP, "Les indications de type ne peuvent être que de type objet et tableau (puisque PHP 5.1). Les indications de type traditionnelles avec int et string ne sont pas prises en charge". L'erreur est déroutante à cause de votre choix de "chaîne" - mettez "myClass" à sa place et l'erreur sera lue différemment: "L'argument 1 transmis à phpwtf () doit être une instance de myClass, chaîne donnée"

8
Surreal Dreams

Comme d’autres l’ont déjà dit, les indications de type ne fonctionnent actuellement que pour les types d’objet. Mais je pense que l'erreur particulière que vous avez déclenchée pourrait être liée à la préparation du type de chaîne à venir SplString .

En théorie, il se comporte comme une chaîne, mais comme il s'agit d'un objet, la vérification du type d'objet est validée. Malheureusement, il n'est pas encore dans PHP 5.3, il pourrait arriver en 5.4, donc je n'ai pas testé cela.

3
mario

À partir de PHP 7.0, les déclarations de type autorisent les types scalaires. Ces types sont donc disponibles: self, array, callable, bool, float, int, string Les trois premiers étaient disponibles dans PHP 5, mais les quatre derniers sont nouveaux dans PHP 7. Si vous utilisez autre chose (par exemple, integer ou boolean) qui sera interprété comme un nom de classe.

Voir le manuel PHP pour plus d'informations .

2
TwoStraws

J'ai eu cette erreur en appelant une fonction d'un contrôleur Laravel dans un fichier PHP.

Après quelques heures, j'ai trouvé le problème: j'utilisais $ this dans une fonction statique.

0
ecairol

(posté à l'origine par leepowers dans sa question)

Le message d'erreur est déroutant pour une grande raison:

Les noms de type primitifs ne sont pas réservés dans PHP

Voici toutes les déclarations de classe valides:

class string { }
class int { }
class float { }
class double { }

Mon erreur a été de penser que le message d'erreur faisait uniquement référence au type primitif de chaîne - le mot "instance" aurait dû me mettre en pause. Un exemple pour illustrer davantage:

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')]);

Sortie:

$ s1 - chaîne primitive? oui - instance de chaîne? non

$ s2 - chaîne primitive? non - instance de chaîne? Oui

Dans PHP, il est possible qu'une string soit une string sauf s'il s'agit en réalité d'une string Comme dans tout langage utilisant la conversion de type implicite, le contexte est primordial.

0
vaxquis