Wie kann man vor PHP 7 "muss eine Instanz einer Zeichenfolge sein, Zeichenfolge angegeben" auflösen?

217

Hier ist mein Code:

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

Was zu diesem Fehler führt:

Fangender schwerwiegender Fehler: Argument 1, das an phpwtf () übergeben wird, muss eine Instanz von Zeichenfolge sein, Zeichenfolge angegeben

Es ist mehr als ein bisschen Orwellianisch zu sehen, wie PHP den gewünschten Typ in einem Atemzug erkennt und ablehnt. Es gibt fünf Lichter, verdammt.

Was entspricht der Typangabe für Zeichenfolgen in PHP? Bonus Rücksicht auf die Antwort, die genau erklärt, was hier los ist.

Leepowers
quelle
5
Das liegt daran, dass Sie es falsch machen. Ihr Code soll zunächst nicht funktionieren. Informieren Sie sich über das Jonglieren von Typen in PHP-Dokumenten. PHP ist dynamisch und schwach typisiert. Sie können (string) verwenden, um ein Argument in einen String umzuwandeln (allerdings nur im Funktionskörper), aber Sie können nur Objekte und Arrays andeuten, wie Sie es in Ihrem Code-Snippet tun.
Richard Knop
7
Das Problem ist, dass Sie einen kleinen Fehler gemacht haben. Es gibt vier Lichter!
CJ Dennis
@ Gordon, ich habe auf 5.6 getestet. Immer noch kein Glück.
Pacerier
@Pacerier Bitte folgen Sie wiki.php.net/rfc für die neuesten Entwicklungen.
Gordon
3
Anscheinend wurde die skalare Typ-Andeutung (wie OP intuitiv erwartet wird) laut Quelle unter einem RFC für PHP * 7 * genehmigt . Der genehmigte RFC bietet offenbar auch syntaktischen Zucker für die Typprüfung von Rückgabewerten sowie Parameter (Argumente). Es hat lange gedauert.
Selten needy

Antworten:

204

Vor PHP 7 können Typhinweise nur verwendet werden, um die Arten von Objekten und Arrays zu erzwingen. Skalartypen sind nicht typisierbar. In diesem Fall wird ein Objekt der Klasse stringerwartet, aber Sie geben ihm einen (Skalar) string. Die Fehlermeldung mag lustig sein, sollte aber zunächst nicht funktionieren. Angesichts des dynamischen Typisierungssystems macht dies tatsächlich einen perversen Sinn.

Sie können Skalartypen nur manuell "Tipp" eingeben:

function foo($string) {
    if (!is_string($string)) {
        trigger_error('No, you fool!');
        return;
    }
    ...
}
täuschen
quelle
1
@deceze, Gibt es eine Syntax für Hinweise auf umgekehrte Typen? ZB alles andere als Arrays.
Pacerier
@ Pacerier Nein, gibt es nicht.
Täuschung
4
Diese Antwort gilt nicht für PHP 7
Jose Nobile
24

Aus dem PHP-Handbuch :

Typhinweise können nur vom Typ Objekt und Array (seit PHP 5.1) sein. Herkömmliche Typhinweise mit int und string werden nicht unterstützt.

Also hast du es. Die Fehlermeldung ist nicht wirklich hilfreich, das gebe ich Ihnen aber.

** 2017 bearbeiten **

PHP7 führte weitere Funktionsdatentypdeklarationen ein, und der oben genannte Link wurde zu Funktionsargumenten verschoben : Typdeklarationen . Von dieser Seite:

Gültige Typen

  • Klassen- / Schnittstellenname : Der Parameter muss eine Instanz des angegebenen Klassen- oder Schnittstellennamens sein. (seit PHP 5.0.0)
  • self : Der Parameter muss eine Instanz derselben Klasse sein wie die, für die die Methode definiert ist. Dies kann nur für Klassen- und Instanzmethoden verwendet werden. (seit PHP 5.0.0)
  • Array : Der Parameter muss ein Array sein. (seit PHP 5.1.0) aufrufbar Der Parameter muss ein gültiger aufrufbarer Parameter sein. PHP 5.4.0
  • bool : Der Parameter muss ein boolescher Wert sein. (seit PHP 7.0.0)
  • float : Der Parameter muss eine Gleitkommazahl sein. (seit PHP 7.0.0)
  • int : Der Parameter muss eine Ganzzahl sein. (seit PHP 7.0.0)
  • Zeichenfolge : Der Parameter muss eine Zeichenfolge sein. (seit PHP 7.0.0)
  • iterable : Der Parameter muss entweder ein Array oder eine Instanz von Traversable sein. (seit PHP 7.1.0)

Warnung

Aliase für die oben genannten Skalartypen werden nicht unterstützt. Stattdessen werden sie als Klassen- oder Schnittstellennamen behandelt. Wenn Sie beispielsweise den Booleschen Wert als Parameter oder Rückgabetyp verwenden, ist ein Argument oder ein Rückgabewert erforderlich, der eine Instanz des Klassen- oder Schnittstellen-Booleschen Werts und nicht des Typs Bool ist:

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

Das obige Beispiel gibt Folgendes aus:

 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

Die letzte Warnung ist tatsächlich wichtig, um den Fehler "Argument muss vom Typ Zeichenfolge, Zeichenfolge angegeben" zu verstehen. Da meist nur Klassen- / Schnittstellennamen als Argumenttyp zulässig sind, versucht PHP, einen Klassennamen "string" zu finden, kann jedoch keinen finden, da es sich um einen primitiven Typ handelt. Daher schlägt dieser unangenehme Fehler fehl.

Yanick Rochon
quelle
8

PHP ermöglicht "Hinweise", wo Sie eine Klasse angeben, um ein Objekt anzugeben. Laut PHP-Handbuch können "Typhinweise nur vom Typ Objekt und Array (seit PHP 5.1) sein. Herkömmliche Typhinweise mit int und string werden nicht unterstützt." Der Fehler ist verwirrend, weil Sie "string" gewählt haben - setzen Sie "myClass" an seine Stelle und der Fehler wird anders lauten: "Argument 1, das an phpwtf () übergeben wird, muss eine Instanz von myClass sein, String angegeben"

Surreale Träume
quelle
3

Wie andere bereits gesagt haben, funktioniert die Typhinweise derzeit nur für Objekttypen. Ich denke jedoch, dass der von Ihnen ausgelöste Fehler möglicherweise in der Vorbereitung des kommenden Zeichenfolgentyps SplString liegt .

Theoretisch verhält es sich wie eine Zeichenfolge, aber da es sich um ein Objekt handelt, würde es die Objekttypüberprüfung bestehen. Leider ist es noch nicht in PHP 5.3, möglicherweise in 5.4, also habe ich es nicht getestet.

Mario
quelle
2

Ab PHP erlauben 7.0 Typdeklarationen skalare Typen, so sind diese Typen jetzt verfügbar: self, array, callable, bool, float, int, string. Die ersten drei waren in PHP 5 verfügbar, aber die letzten vier sind neu in PHP 7. Wenn Sie etwas anderes (z. B. integeroder boolean) verwenden, wird dies als Klassenname interpretiert.

Weitere Informationen finden Sie im PHP-Handbuch .

TwoStraws
quelle
0

Vielleicht nicht sicher und hübsch, aber wenn Sie müssen:

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"));
Patrick
quelle
5
Ich könnte noch einennew string(array(1,2,3))
Jimmy T.
0

Ich habe diesen Fehler beim Aufrufen einer Funktion von einem Laravel Controller in eine PHP-Datei erhalten.

Nach ein paar Stunden fand ich das Problem: Ich habe $ this innerhalb einer statischen Funktion verwendet.

Ecairol
quelle
Using $this when not in object contextist in der Tat eine kryptische Nachricht.
Ben Fransen
0

(ursprünglich von Leepowers in seiner Frage gepostet )

Die Fehlermeldung ist aus einem großen Grund verwirrend:

Primitive Typnamen sind in PHP nicht reserviert

Das Folgende sind alle gültigen Klassendeklarationen:

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

Mein Fehler bestand darin zu denken, dass sich die Fehlermeldung ausschließlich auf den primitiven Typ der Zeichenfolge bezog - das Wort 'Instanz' hätte mir eine Pause geben sollen. Ein Beispiel zur weiteren Veranschaulichung:

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

Ausgabe:

$ s1 - primitiver String? Ja - String-Instanz? Nein

$ s2 - primitiver String? no - string Instanz? Ja

In PHP ist es möglich string, dass a ein ist, stringaußer wenn es tatsächlich ein ist string. Wie bei jeder Sprache, die implizite Typkonvertierung verwendet, ist der Kontext alles.

user719662
quelle
-1

Ich denke, Typografie auf PHP im inneren Block, String auf PHP ist kein Objekt, wie ich weiß:

<?php
function phpwtf($s) {
    $s = (string) $s;
    echo "$s\n";
}
phpwtf("Type hinting is da bomb");
subosito
quelle
2
Sie können innerhalb Ihrer Funktion eine is_string () - Validierung hinzufügen, um zu verhindern, dass andere Werte an die Funktion übergeben werden.
Subosito
1
(string) $skann einen Fehler auslösen, wenn $ses sich um ein Objekt handelt, das nicht in einen String umgewandelt werden kann (es ist keine __toString()Methode implementiert), daher ist es nicht so einfach
Yanick Rochon
Ja Yanick, du hast recht. Aber wir können nicht alle Eingaben zwingen, Zeichenfolgen zu sein, oder? Deshalb kommt die Ausnahme ins Spiel. Wir können eine Art von Validierungen kombinieren und Ausnahmen für den Rest abfangen;)
subosito
Ich sage nur, dass das Umwandeln einer Variablen in einen String, ohne vorher zu prüfen, ob die Variable umgewandelt werden kann, vermieden werden sollte, hauptsächlich weil das Abfangen von Ausnahmen kostspielig ist und zu schlechten Entwurfsmustern / Codierungsgewohnheiten führt.
Yanick Rochon