Was machen strenge Typen in PHP?

145

Ich habe die folgende neue Zeile in PHP 7 gesehen, aber niemand erklärt wirklich, was es bedeutet. Ich habe es gegoogelt und alles, worüber sie sprechen, ist, ob Sie es aktivieren oder nicht wie eine Umfrage.

declare(strict_types = 1);

Was tut es? Wie wirkt es sich auf meinen Code aus? Sollte ich es tun?

Eine Erklärung wäre schön.

Sufuko
quelle
5
Schauen Sie sich auch diese php.net/manual/en/… für die Anweisung
strict_types an

Antworten:

152

Aus dem Baumhaus-Blog :

Mit PHP 7 haben wir jetzt Skalartypen hinzugefügt. Insbesondere: int, float, string und bool.

Durch Hinzufügen von Hinweisen zum Skalartyp und Aktivieren strenger Anforderungen wird gehofft, dass korrektere und selbstdokumentierendere PHP-Programme geschrieben werden können. Es gibt Ihnen auch mehr Kontrolle über Ihren Code und kann das Lesen des Codes erleichtern.

Standardmäßig sind skalare Typdeklarationen nicht streng, dh sie versuchen, den ursprünglichen Typ so zu ändern, dass er dem in der Typdeklaration angegebenen Typ entspricht. Mit anderen Worten, wenn Sie eine Zeichenfolge, die mit einer Zahl beginnt, an eine Funktion übergeben, für die ein Gleitkomma erforderlich ist, wird die Zahl von Anfang an erfasst und alles andere entfernt. Das Übergeben eines Floats an eine Funktion, die ein int erfordert, wird zu int (1).

Standardmäßig wandelt PHP Werte des falschen Typs nach Möglichkeit in den erwarteten Skalartyp um. Beispielsweise erhält eine Funktion, die eine Ganzzahl für einen Parameter erhält, der eine Zeichenfolge erwartet, eine Variable vom Typ Zeichenfolge.

Strenge Typen deaktiviert ( Bewertung ):

<?php

  function AddIntAndFloat(int $a, float $b) : int
  {
      return $a + $b;
  }

  echo AddIntAndFloat(1.4, '2');
  /*
  * without strict typing, PHP will change float(1.4) to int(1)
  * and string('2') to float(2.0) and returns int(3)
  */

Es ist möglich, den strengen Modus pro Datei zu aktivieren. Im strengen Modus wird nur eine Variable vom genauen Typ der Typdeklaration akzeptiert oder ein TypeError ausgelöst. Die einzige Ausnahme von dieser Regel besteht darin, dass einer Funktion, die einen Float erwartet, eine Ganzzahl zugewiesen werden kann. Funktionsaufrufe innerhalb interner Funktionen sind von der Deklaration strict_types nicht betroffen.

Um den strengen Modus zu aktivieren, wird die Anweisung declare mit der Deklaration strict_types verwendet:

Strenge Typen aktiviert ( Bewertung ):

<?php declare(strict_types=1);

  function AddIntAndFloat(int $a, float $b): int
  {
      return (string) $a + $b;
  }

  echo AddIntAndFloat(1.4,'2');
  // Fatal error: Uncaught TypeError: Argument 1 passed to AddIntAndFloat() must be of the type int, float given
  echo AddIntAndFloat(1,'2');
  // Fatal error: Uncaught TypeError: Argument 2 passed to AddIntAndFloat() must be of the type float, string given

  // Integers can be passed as float-points :
  echo AddIntAndFloat(1,1);
  // Fatal error: Uncaught TypeError: Return value of AddIntAndFloat() must be of the type integer, string returned

Arbeitsbeispiel:

<?php

declare(strict_types=1);

function AddFloats(float $a, float $b) : float
{
    return $a+$b;
}

$float = AddFloats(1.5,2.0); // Returns 3.5

function AddFloatsReturnInt(float $a, float $b) : int
{
    return (int) $a+$b;
}

$int = AddFloatsReturnInt($float,1.5); // Returns 5

function Say(string $message): void // As in PHP 7.2
{
    echo $message;
}

Say('Hello, World!'); // Prints "Hello, World!"

function ArrayToStdClass(array $array): stdClass
{
    return (object) $array;
}

$object = ArrayToStdClass(['name' => 'azjezz','age' => 100]); // returns an stdClass

function StdClassToArray(stdClass $object): array
{
    return (array) $object;
}

$array = StdClassToArray($object); // Returns array

function ArrayToObject(array $array): object // As of PHP 7.2
{
    return new ArrayObject($array);
}

function ObjectToArray(ArrayObject $object): array
{
    return $object->getArrayCopy();
}

var_dump( ObjectToArray( ArrayToObject( [1 => 'a' ] ) ) ); // array(1 => 'a');
saif
quelle
3
Der erste schwerwiegende Fehler, der in Ihrem Beispiel für aktivierte strikte Typen erwähnt wird, ist falsch. Wie in der Dokumentation erwähnt: "Die einzige Ausnahme von dieser Regel besteht darin, dass einer Funktion, die einen Float erwartet, eine Ganzzahl zugewiesen werden kann." Der Funktionsaufruf würde auf dem int nicht fehlschlagen. Es würde aber auf der Saite.
Paul
63

strict_types beeinflusst den Typenzwang.

Die Verwendung von Typhinweisen ohne strict_typeskann zu subtilen Fehlern führen.

Vor strengen Typen int $xbedeutet " $xmuss einen Wert haben, der zu einem int erzwungen werden kann ". Jeder Wert, der zu einem erzwungen werden könnte, intwürde den Typhinweis übergeben, einschließlich:

  • ein int richtig ( 242),
  • ein float ( 10.17),
  • ein bool ( true),
  • null, oder
  • eine Zeichenfolge mit führenden Ziffern ( "13 Ghosts").

Durch die Einstellung strict_types=1teilen Sie der Engine mit, dass int $x"$ x nur ein int-Eigen sein darf, kein Zwang vom Typ erlaubt ist." Sie haben die große Sicherheit, dass Sie genau und nur das bekommen, was gegeben wurde, ohne Konvertierung und potenziellen Verlust.

Beispiel:

<?php
function get_quantity(): int {
    return '100 apples';
}
echo get_quantity() . PHP_EOL;

Ergibt ein möglicherweise verwirrendes Ergebnis:

Notice: A non well formed numeric value encountered in /Users/bishop/tmp/pmkr-994/junk.php on line 4
100

Die meisten Entwickler würden, glaube ich, einen intHinweis erwarten, der "nur ein int" bedeutet. Aber das tut es nicht, es bedeutet "so etwas wie ein Int". Das Aktivieren von strict_types ergibt das wahrscheinlich erwartete und gewünschte Verhalten:

<?php declare(strict_types=1);

function get_quantity(): int {
    return '100 apples';
}
echo get_quantity() . PHP_EOL;

Ausbeuten:

Fatal error: Uncaught TypeError: Return value of get_quantity() must be of the type int, string returned in example.php:4

Ich denke, hier gibt es zwei Lektionen, wenn Sie Tipphinweise verwenden:

  • Verwenden Sie strict_types=1immer.
  • Konvertieren Sie Benachrichtigungen in Ausnahmen, falls Sie vergessen, das strict_typesPragma hinzuzufügen .
Bischof
quelle
1
Dies wurde bereits wie vor fast einem Jahr gut beantwortet;)
Emix
6
In der Tat habe ich die andere Antwort @emix hochgestimmt. Ich hatte jedoch das Gefühl, dass die Frage "sollte ich es tun" nicht angesprochen wurde. Ich hatte auch das Gefühl, dass ein kompakteres und schockierenderes Beispiel die Menschen dazu ermutigen würde, es zu verwenden strict_types.
Bischof
1
Ich denke, diese Frage spricht kurz und bündig das "Soll ich es tun?" Teil der Frage des OP. Nach einer kurzen Pause zu PHP zurückzukehren, war sehr hilfreich.
Darragh Enright