Neuerungen in PHP 7
Thema:
Autor:
E-Mail:
Web:
Thema dieses Blog-Artikels sind wichtige Neuerungen in PHP 7.
PHP (rekursives Akronym für „PHP: Hypertext Preprocessor“) ist eine serverseitige objektorientierte Skriptsprache, welche für die Webentwicklung entworfen wurde. Bei der Entwicklung von Websites ist PHP die mit Abstand am häufigsten serverseitig verwendete Programmiersprache. Neben der hauptsächlichen Verwendung von PHP bei der Webentwicklung kann PHP darüber hinaus auch sowohl bei der Kommandozeilenprogrammierung als auch bei der Programmierung von Desktop-Applikationen eingesetzt werden. Die neuste Hauptversion PHP 7 beinhaltet u. a. hinsichtlich der schon hohen Ausführungsgeschwindigkeit eine nochmalige, enorme Verbesserung im Vergleich zur Vorgängerversion PHP 5.
In PHP 7.0 wurden die folgenden Neuerungen eingeführt:
- Scalar type declarations
- Return type declarations
- Null coalescing operator
- Spaceship operator
- Anonymous classes
- Closure::call()
In PHP 7.1 kamen die folgenden Neuerungen hinzu:
- Class constant visibility
- Nullable types
- Void functions
- iterable pseudo-type
- Multi catch exception handling
- Convert callables to Closures with Closure::fromCallable()
Nachfolgend wird anhand zweier Code-Beispiele auf die wesentlichen (fett markierten) Neuerungen in PHP 7 eingegangen.
Beginnen wir zunächst mit den wesentlichen Neuerungen in PHP 7.0.
Hier wurden die scalar type declarations und die return type declarations eingeführt:
Scalar type declarations (Skalartyp-Deklarationen):
Die Skalartyp-Deklarationen existieren in zwei verschiedenen Ausprägungen respektive Modi, nämlich „coercive“ (zwingend) und „strict“ (streng). Insofern kein Modus angegeben wird, ist der Modus „coercive“ standardmäßig gesetzt (default).
Die folgenden Parameter-Typen können jetzt „erzwungen“ werden (Modus „coercive“ oder „strict“):
- strings (string)
- integers (int)
- floating-point numbers (float)
- booleans (bool)
Sie ergänzen die anderen Typen, welche in PHP 5 eingeführt wurden: class names, interfaces, array und callable.
Um den „strict“ Modus zu aktivieren, muss eine einzelne „declare“ Direktive am Anfang einer Datei gesetzt werden. Dies bedeutet, dass die Strenge bzw. Genauigkeit der Skalartypisierung anhand der jeweiligen Datei festgelegt wird. Die „declare“ Direktive wirkt sich nicht nur auf die Typdeklarationen der Parameter aus, sondern auch auf den Rückgabetyp einer Funktion (return type declarations), auf integrierte PHP Funktionen, und auf Funktionen von geladenen Erweiterungen.
Return type declarations (Rückgabetyp-Deklarationen):
PHP 7 fügt Unterstützung für Rückgabetyp-Deklarationen hinzu. Ähnlich wie Argumenttyp-Deklarationen spezifizieren Rückgabetyp-Deklarationen den Typ des Wertes, der von einer Funktion zurückgegeben wird. Dieselben Typen welche für die Argumenttyp-Deklarationen verfügbar sind, sind auch für die Rückgabetyp-Deklarationen verfügbar.
Nachfolgend wird ein PHP 7 Code-Beispiel für die Verwendung von scalar type declarations und return type declarations aufgelistet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
<?php /* === HyperCube IT Solutions === File: shopping-cart-item.class.php Author: Christian Paulus Email: c.paulus@hypercube.biz Web: www.hypercube.biz # PHP 7.0 example # => Scalar type declarations => Return type declarations */ /* strict mode */ declare(strict_types = 1); /* class */ class ShoppingCartItem { /* properties */ public $shoppingCartId = -1; public $customerId = -1; public $articleNumberId = -1; public $articleType = null; public $articleDescription = null; public $jsonArticleProperties = null; public $articleImageFileName = null; public $numberOfArticles = -1; public $unitPrice = -1.0; public $totalPrice = -1.0; /* constructor */ public function __construct(int $shoppingCartId, int $customerId, int $articleNumberId, string $articleType, string $articleDescription, string $jsonArticleProperties, string $articleImageFileName, int $numberOfArticles, float $unitPrice, float $totalPrice) { $this->shoppingCartId = $shoppingCartId; $this->customerId = $customerId; $this->articleNumberId = $articleNumberId; $this->articleType = $articleType; $this->articleDescription = $articleDescription; $this->jsonArticleProperties = $jsonArticleProperties; $this->articleImageFileName = $articleImageFileName; $this->numberOfArticles = $numberOfArticles; $this->unitPrice = $unitPrice; $this->totalPrice = $totalPrice; } /* destructor */ public function __destruct() {} /* method */ public function recalculateTotalPrice(int $numberOfArticles): float { $this->numberOfArticles = $numberOfArticles; $this->totalPrice = $this->unitPrice * $this->numberOfArticles; return $this->totalPrice; } // ... } ?> |
Der Klasse ShoppingCartItem werden über Constructor Injection deklarierte Skalartypen übergeben (scalar type declarations). Diese übergebenen Parameter sind vom Typ int, string und float. Der Methode recalculateTotalPrice wird über Setter Injection ebenfalls ein deklarierter Skalartyp übergeben (scalar type declaration). Der übergebene Parameter ist vom Typ int. Die Methode gibt als deklarierten Rückgabetyp ein float zurück (return type declaration).
Mit der Direktive declare(strict_types = 1); wurde der Modus für die Skalartyp-Deklarationen und Rückgabetyp-Deklarationen von coercive explizit auf strict gesetzt. Der Modus strict bedeutet in diesem Zusammenhang, dass die entsprechenden Werte genau respektive streng von diesem Typ sein müssen und keine „typungleiche“ Werte (coercive) zulässig sind.
Beispiel:
Im Modus strict würde die Übergabe eines string Wertes „12“ für den als int deklarierten Parameter $numberOfArticles (Anzahl von Artikel) zu einer Fehlermeldung führen. Im Modus coercive hingegen würde die Übergabe akzeptiert werden und der string „12“ in einen int 12 gewandelt werden (Stichwort: type juggling in PHP). Die Übergabe eines string Wertes „12ab“ hingegen würde in beiden Modi (strict und coercive) zu einer Fehlermeldung führen, da der String „12ab“ keine Zahl ist bzw. in keine Zahl gewandelt werden kann.
Ein Anwendungsbeispiel für die Klasse ShoppingCartItem sieht wie folgt aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<?php /* === HyperCube IT Solutions === File: web-shop-example.php Author: Christian Paulus Email: c.paulus@hypercube.biz Web: www.hypercube.biz # PHP 7.0 example # => Scalar type declarations => Return type declarations */ /* strict mode */ declare(strict_types = 1); /* imports */ require_once("shopping-cart-item.class.php"); /* Web Shop Example */ echo "== Web Shop Example ==" . PHP_EOL; $shoppingCartItem = new ShoppingCartItem(3, 1107, 8001, "IP Profil", "IP Profil mit Schutzklasse 7", "Länge: 2000 mm, Breite: 24 mm, Höhe: 20 mm", "IP-02-15.jpg", 1, 19.00, 19.00); $totalPrice = $shoppingCartItem->recalculateTotalPrice(3); echo "Total Price: " . $totalPrice . " Euro" . PHP_EOL; /* object properties */ echo PHP_EOL; echo "(object properties)" . PHP_EOL; echo "numberOfArticles: " . $shoppingCartItem->numberOfArticles . PHP_EOL; echo "totalPrice: " . $shoppingCartItem->totalPrice . PHP_EOL; ?> |
Ein Objekt der Klasse ShoppingCartItem (Warenkorbposition) wird erzeugt und über Constructor Injection mit entsprechenden Werten initialisiert. Anschließend wird die Methode recalculateTotalPrice des initialisierten Objekts aufgerufen und ihr als Parameter für die Anzahl der Artikel den Wert 3 übergeben. Das Objekt wurde zuvor für die Anzahl der Artikel mit dem Wert 1 und für den Einzelpreis und Gesamtpreis mit jeweils dem Wert 19.0 initialisiert. Der Aufruf der Methode recalculateTotalPrice mit dem Wert 3 als Übergabeparameter liefert nun als Rückgabewert 57.0 (3 Artikel x 19.0 Euro Einzelpreis = 57.0 Euro Gesamtpreis). Die Objektvariable $numberOfArticles (Anzahl der Artikel) wurde vom Wert 1 auf den Wert 3 geändert, die Objektvariable $totalPrice (Gesamtpreis) wurde vom Wert 19.0 auf den Wert 57.0 geändert.
Die Ausführung der PHP Datei web-shop-example.php in einer Shell liefert das folgende Ergebnis:
Ausführung der Datei "web-shop-example.php"
Als nächstes kommen wir zu den wesentlichen Neuerungen in PHP 7.1.
Hier wurden die class constant visibility, die nullable types sowie die void functions eingeführt:
Class constant visibility (Klassenkonstanten-Sichtbarkeit):
PHP 7.1 ermöglicht die Sichtbarkeit von Klassenkonstanten anzugeben. Die Sichtbarkeit kann entsprechend mit den Schlüsselwörtern public, protected oder private festgelegt werden. Wird eine Klassenkonstante durch das Schlüsselwort const ohne ein vorangestelltes Schlüsselwort für die Sichtbarkeit definiert, so ist die Sichtbarkeit standardmäßig public (default).
Nullable types (Nullable-Typen):
Typdeklarationen für Parameter und Rückgabewerte können nun als „nullable“ angegeben werden, indem beim Typnamen ein Fragezeichen (?) vorangestellt wird. Dies bedeutet, dass sowohl der spezifizierte Typ als auch NULL als Argument übergeben bzw. als einen Wert zurückgegeben werden kann.
Void functions (Void-Funktionen):
Es wurde ein void-Rückgabetyp eingeführt. Funktionen, die mit void als ihren Rückgabetyp deklariert wurden, müssen entweder ihr ganzes „return statement“ (Rückkehranweisung) weglassen, oder aber ein leeres „return statement“ (Rückkehranweisung) verwenden. NULL ist kein gültiger Rückgabewert für eine void-Funktion.
Nachfolgend wird ein PHP 7 Code-Beispiel für die Verwendung von class constant visibility, nullable types und void functions aufgelistet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
<?php /* === HyperCube IT Solutions === File: customer-dao.class.php Author: Christian Paulus Email: c.paulus@hypercube.biz Web: www.hypercube.biz PHP 7.1 example => Class constant visibility => Nullable types => Void functions */ /* strict mode */ declare(strict_types = 1); /* class */ class CustomersDAO { /* properties */ // table private const TABLE_CUSTOMERS = "customers"; // table columns private const COLUMN_CUSTOMER_ID = "CUSTOMER_ID"; private const COLUMN_EMAIL_ADDRESS = "Email_Address"; private const COLUMN_PASSWORD = "Password"; private const COLUMN_CUSTOMER_TYPE = "Customer_Type"; private const COLUMN_USERNAME = "Username"; private const COLUMN_FIRST_NAME = "First_Name"; private const COLUMN_LAST_NAME = "Last_Name"; private const COLUMN_STREET = "Street"; private const COLUMN_HOUSE_NUMBER = "House_Number"; private const COLUMN_POSTAL_CODE = "Postal_Code"; private const COLUMN_TOWN = "Town"; private const COLUMN_COUNTRY = "Country"; // ... protected const ADMIN_MODE = "ADMIN_MODE"; public const CUSTOMER_TYPE_PRIVATE = "PRIVATE"; public const CUSTOMER_TYPE_CORPORATE = "CORPORATE"; private function __construct() {} private function __clone() {} /* method */ public static function login(string $emailAddress, string $password, mysqli $mySQLi): ?Customer { $password = sha1($password); // ... // SQL select $sqlSelect = "SELECT " . self::COLUMN_CUSTOMER_ID . ", " . self::COLUMN_CUSTOMER_TYPE . ", " . self::COLUMN_USERNAME . ", " . self::COLUMN_EMAIL_ADDRESS . ", " . self::COLUMN_FIRST_NAME . ", " . self::COLUMN_LAST_NAME . ", " . self::COLUMN_STREET . ", " . self::COLUMN_HOUSE_NUMBER . ", " . self::COLUMN_POSTAL_CODE . ", " . self::COLUMN_TOWN . ", " . self::COLUMN_COUNTRY . " " . "FROM " . self::TABLE_CUSTOMERS . " " . "WHERE LOWER(" . self::COLUMN_EMAIL_ADDRESS . ") = ? " . "AND " . self::COLUMN_PASSWORD . " = ?"; // prepare statement $mySQLiStatement = $mySQLi->prepare($sqlSelect); // bind parameters to prepared statement $emailAddress = strtolower($emailAddress); $mySQLiStatement->bind_param("ss", $emailAddress, $password); // execute prepared statement $mySQLiStatement->execute(); // create result $mySQLiStatement->store_result(); $affectedRows = $mySQLiStatement->affected_rows; $customer = null; if ($affectedRows > 0) { // Customer with correct password found $mySQLiStatement->bind_result($customerId, $customerType, $username, $emailAddress, $firstName, $lastName, $street, $houseNumber, $postalCode, $town, $country); $mySQLiStatement->fetch(); $customer = new Customer((int) $customerId, $customerType, $username, $emailAddress, $firstName, $lastName, $street, $houseNumber, $postalCode, $town, $country); } $mySQLiStatement->free_result(); $mySQLiStatement->close(); return $customer; } /* method */ public static function saveSetting(string $name, string $value, mysqli $mySQLi): void { // method implementation // ... } // ... } ?> |
In der Klasse CustomersDAO werden entsprechende Klassenkonstanten u. a. für den Zugriff auf Daten in einer Datenbanktabelle names Customers (Kunden) definiert. Das Wort DAO (Data Access Object, Datenzugriffsobjekt) im Klassennamen bedeutet, dass es sich hierbei um eine Klasse für den Zugriff auf Daten (in z. B. einer Datenbank oder Datei) handelt. Die Klassenkonstanten für den Tabellennamen (TABLE_CUSTOMERS) und die entsprechenden Tabellenspalten (COLUMN_CUSTOMER_ID, COLUMN_EMAIL_ADDRESS, etc.) wurden private definiert (class constant visibility). Daneben existiert beispielsweise noch eine mit protected definierte Klassenkonstante namens ADMIN_MODE die angibt, ob es sich um einen Administrator-Modus handelt. Schließlich existieren noch zwei mit public definierte Klassenkonstanten namens CUSTOMER_TYPE_PRIVATE und CUSTOMER_TYPE_CORPORATE für die Kategorisierung von Privat- und Firmenkunden.
Der Rückgabetyp der statischen Methode login wurde als nullable type deklariert (nullable type). Es wird somit entweder ein Objekt der Klasse Customer (bei einem erfolgreichen Login) oder aber NULL (bei einem Login-Fehler) zurückgegeben.
Für das Speichern von Benutzereinstellungen ist eine statische Methode namens saveSettings vorgesehen, die nach ihrer Ausführung keinen Wert zurückgibt und somit als Rückgabetyp void deklariert (void function).
Quellenangaben:
- PHP Manual: www.php.net
- Migrating from PHP 5.6.x to PHP 7.0.x (New Features): www.php.net/manual/en/migration70.new-features.php
- Migrating from PHP 7.0.x to PHP 7.1.x (New Features): www.php.net/manual/en/migration71.new-features.php