Hoe op te lossen “moet een instantie van string zijn, string opgegeven” voorafgaand aan PHP 7?

Hier is mijn code:

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

Wat resulteert in deze fout:

Ontvangbare fatale fout: argument 1 doorgegeven aan phpwtf() moet een instantie van string zijn, string gegeven

Het is meer dan een beetje Orwelliaans om PHP het gewenste type in één adem te zien herkennen en afwijzen. Er zijn vijf lichten, verdomme.

Wat is het equivalent van typehints voor strings in PHP? Bonusoverweging voor het antwoord dat precies uitlegt wat hier aan de hand is.


Antwoord 1, autoriteit 100%

Voorafgaand aan PHP 7 kan typehintingalleen worden gebruikt om de typen objecten en reeksen. Scalaire typen zijn niet typeaanwijzingen. In dit geval wordt een object van de klasse stringverwacht, maar je geeft het een (scalaire) string. De foutmelding is misschien grappig, maar het zou om te beginnen niet moeten werken. Gezien het dynamische typesysteem is dit eigenlijk een soort perverse betekenis.

Je kunt alleen handmatig“hint” scalaire typen:

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

Antwoord 2, autoriteit 12%

Van PHP-handleiding:

Type Hints kunnen alleen van het type object en array zijn (sinds PHP 5.1). Traditionele typehints met int en string worden niet ondersteund.

Dus je hebt het. De foutmelding is niet echt nuttig, dat geef ik je wel.

** 2017 Bewerken **

PHP7 heeft meer functiegegevenstypedeclaraties geïntroduceerd en de bovengenoemde link is verplaatst naar Functieargumenten : Typ declaraties. Vanaf die pagina :

Geldige typen

  • Klasse/interfacenaam: De parameter moet een instantie zijn van de opgegeven klasse of interfacenaam. (sinds PHP 5.0.0)
  • self: de parameter moet een instantie zijn van dezelfde klasse als die waarop de methode is gedefinieerd. Dit kan alleen worden gebruikt voor klasse- en instantiemethoden. (sinds PHP 5.0.0)
  • array: de parameter moet een array zijn. (sinds PHP 5.1.0)
  • callable: de parameter moet een geldige callable zijn. (sinds PHP 5.4.0)
  • boole: de parameter moet een booleaanse waarde zijn. (sinds PHP 7.0.0)
  • float: de parameter moet een getal met drijvende komma zijn. (sinds PHP 7.0.0)
  • int: De parameter moet een geheel getal zijn. (sinds PHP 7.0.0)
  • string: De parameter moet een string zijn. (sinds PHP 7.0.0)
  • iterable: de parameter moet een array of een instantie van Traversable zijn. (sinds PHP 7.1.0)

Waarschuwing

Aliases voor de bovenstaande scalaire typen worden niet ondersteund. In plaats daarvan worden ze behandeld als klasse- of interfacenamen. Het gebruik van boolean als parameter of retourtype vereist bijvoorbeeld een argument of retourwaarde die een instantie is van de klasse of interface boolean, in plaats van van het type bool:

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

Het bovenstaande voorbeeld geeft het volgende weer:

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

De laatste waarschuwing is eigenlijk belangrijk om de fout “Argument moet van het type string, string gegeven” te begrijpen; aangezien meestal alleen klasse-/interfacenamen als argumenttype zijn toegestaan, probeert PHP een klassenaam “string” te lokaliseren, maar kan er geen vinden omdat het een primitief type is, dus mislukken met deze lastige fout.


Antwoord 3, autoriteit 4%

PHP staat “hinting” toe waarbij je een klasse opgeeft om een ​​object te specificeren. Volgens de PHP-handleiding kunnen “Type Hints alleen van het type object en array (sinds PHP 5.1) zijn. Traditionele typehints met int en string worden niet ondersteund.” De fout is verwarrend vanwege uw keuze voor “string” – plaats “myClass” op zijn plaats en de fout zal anders worden gelezen: “Argument 1 doorgegeven aan phpwtf() moet een instantie zijn van myClass, string gegeven”


Antwoord 4

Zoals anderen al hebben gezegd, werkt typehints momenteel alleen voor objecttypen. Maar ik denk dat de specifieke fout die je hebt veroorzaakt, een voorbereiding is op het komende tekenreekstype SplString.

In theorie gedraagt ​​het zich als een string, maar aangezien het een object is, zou het de objecttypeverificatie doorstaan. Helaas is het nog niet in PHP 5.3, komt misschien in 5.4, dus heb dit niet getest.


Antwoord 5

Vanaf PHP 7.0 staan ​​typedeclaraties scalaire typen toe, dus deze typen zijn nu beschikbaar: self, array, callable, bool, float, int, string. De eerste drie waren beschikbaar in PHP 5, maar de laatste vier zijn nieuw in PHP 7. Als u iets anders gebruikt (bijv. integerof boolean) dat wordt geïnterpreteerd als een klasnaam.

Zie de PHP-handleiding voor meer informatie.


Antwoord 6

Misschien niet veilig en mooi, maar als het moet:

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

Antwoord 7

Ik kreeg deze fout bij het aanroepen van een functie van een Laravel Controller naar een PHP-bestand.

Na een paar uur vond ik het probleem: ik gebruikte $thisvanuit een statische functie.


Antwoord 8

(oorspronkelijk geplaatst door leepowersin zijn vraag)

De foutmelding is om één belangrijke reden verwarrend:

Primitieve typenamen zijn niet gereserveerd in PHP

Dit zijn allemaal geldige klasseverklaringen:

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

Mijn fout was dat ik dacht dat de foutmelding alleen naar het primitieve stringtype verwees – het woord ‘instantie’ had me een pauze moeten geven. Een voorbeeld om verder te illustreren:

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

Uitvoer:

$s1 – primitieve string? ja – tekenreeksinstantie? nee

$s2 – primitieve string? nee – string instantie? ja

In PHP is het mogelijk dat een stringeen stringis, behalve wanneer het in werkelijkheid een stringis. Zoals bij elke taal die gebruikmaakt van impliciete typeconversie, is context alles.


Antwoord 9

Ik denk dat typecasting op php op binnenblok, String op PHP geen object is zoals ik weet:

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

Other episodes