PHP Entwicklung. Symfony Konsolen-Komponente - Tipps & Tricks
Dieser Artikel wurde mit dem Ziel erstellt, Ihnen die nützlichsten und abrufbarsten Tipps und Tricks über Symfony Console Development zu zeigen.
Die neue Version von PHP steht vor der Tür. Was sind die neuen Implementierungen, über die Sie Bescheid wissen sollten? Lesen Sie diesen Artikel, um es herauszufinden!
PHP 8.2 steht kurz vor ihrer Veröffentlichung. Vielleicht wird es die Version sein, die ein Upgrade auf PHP 8 für jeden attraktiv erscheinen lässt. Lassen Sie uns darüber sprechen, was Entwickler mit dieser Version erwarten können PHP 8.2 und bereiten Sie sich auf seine neueste Version vor. Aber zuerst wollen wir kurz alle PHP-Versionen und Änderungen im Laufe der Jahre durchgehen.
<?php
class Benutzer {
public int $id;
public string $name;
}
?>
<?php
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);
?>
<?php
Klasse A {}
class B extends A {}
class Producer {
public function method(): A {}
}
class ChildProducer extends Producer {
public function method(): B {}
}
?>
<?php
$array['Schlüssel'] ??= computeDefault();
// ist ungefähr gleichbedeutend mit
if (!isset($array['Schlüssel'])) {
$array['Schlüssel'] = computeDefault();
}
?>
<?php
$parts = ['Apfel', 'Birne'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['Banane', 'Orange', 'Apfel', 'Birne', 'Wassermelone'];
?>
<?php
// Gibt ein Array zurück, das alle notwendigen Zustände des Objekts enthält.
public function __serialize(): array;
// Stellt den Objektzustand aus dem angegebenen Datenarray wieder her.
public function __unserialize(array $data): void;
?>
Die im November 2020 veröffentlichte Version PHP 8.0 bietet die bisher besten Funktionen, darunter:
htmlspecialchars($string, double_encode: false);
Klasse PostsController
{
#[Route("/api/posts/{id}", methods: ["GET"])]
public function get($id) { /* ... */ }
}
Klasse Point {
public function __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) {}
}
Klasse Number {
public function __construct(
private int|Float $number
) {}
}
new Number('NaN'); // TypeError
echo match (8.0) {
'8.0' => "Oh nein!",
8.0 => "Das ist, was ich erwartet habe",
};
//> Das ist das, was ich erwartet habe
$country = $session?->user?->getAddress()?->country;
enum Status
{
Fall Entwurf;
case Veröffentlicht;
Fall Archiviert;
}
function acceptStatus(Status $status) {...}
Klasse BlogData
{
public readonly Status $status;
public function __construct(Status $status)
{
$this->Status = $status;
}
}
$foo = $this->foo(...);
$fn = strlen(...);
Klasse Service
{
private Logger $logger;
public function __construct(
Logger $logger = new NullLogger(),
) {
$this->Logger = $logger;
}
}
function count_and_iterate(Iterator&Countable $value) {
foreach ($wert als $val) {
echo $val;
}
count($value);
}
$response = $httpClient->Request('https://example.com/');
print json_decode($response->getBody()->buffer())['code'];
PHP 8.2 führt weitere Änderungen ein, die darauf abzielen, das Leben des Entwicklers zu erleichtern und seine Arbeit noch mehr zu optimieren. Im Folgenden finden Sie die Liste der neuen Funktionen.
Eine der größten Verbesserungen in der neuen Version von PHP ist die Möglichkeit, direkt eine readonly
Klasse. Eine Klasse, die mit dieser Funktion beschrieben wird, überträgt sie automatisch auf ihre Variablen. DTO-Klassen sehen jetzt ordentlich und sauber aus!
readonly Klasse InvoiceDTO
{
public function __construct(
public UUID $uuid,
public Emittent $issuer,
public DateTime $issuedAt,
) {}
}
Die zweite große Änderung ist die Verwerfung von dynamischen Variablen in Klassen. Die folgende Implementierung wird eine Verwerfung in PHP 8.2 und ErrorException
in der zukünftigen Version des PHP.
Klasse MyUser
{
public string $name;
}
(...)
$myUser->Name = 'Name'; // OK
$myUser->Nachname = 'Nachname'; // veraltet / Fehlermeldung
Es ist erwähnenswert, dass Klassen, die __get
und __set
Methoden und Klassen, die direkt von stdClass
können magische Methoden weiterhin ungehindert einsetzen.
Hier verweise ich auch auf eine interessanter Thread auf GitHubwo die PHP-CS-Entwickler diese Änderung und die Notwendigkeit, ihr beliebtes Tool an die neue Version der Sprache anzupassen, diskutieren.
Zu guter Letzt können Sie dieses Verhalten über Anmerkungen deaktivieren.
#[AllowDynamicProperties]
Klasse MyUser
{
public string $name;
}
$myUser->Nachname = 'Nachname'; // OK
null
, wahr
und falsch
Bislang haben Funktionen, die immer ein wahr
oder falsch
Wert musste mit einem bool
Typ.
function alwaysTrue(): bool { return true; }
Von nun an können wir wahr
und falsch
als einfache Typen in den Rückgabewerten von Funktionen.
function alwaysTrue(): true { return true; }
(DNF) ist eine Standardmethode, um boolesche Ausdrücke zu organisieren. Konkret bedeutet dies die Strukturierung eines booleschen Ausdrucks in eine ODER-verknüpfte Reihe von UNDs. Bei der Anwendung auf Typdeklarationen ermöglicht es eine Standardmethode zur Erstellung kombinierter Unions- und Schnittpunkttypen, die der Parser verarbeiten kann.
Das ist eine große Veränderung, da wir jetzt z. B. nullbare Kreuzungstypen haben können:
function getFullName((HasName&HasNachname)|null $user) { ... }
Ich bin kein großer Befürworter der Verwendung von Traits und eine solche Änderung ist für mich rein kosmetisch, vor allem, da es nicht möglich ist, Trait-Werte ohne Initialisierung des Objekts zu verwenden.
trait Foo {
public const FLAG_1 = 1;
protected const FLAG_2 = 2;
private const FLAG_3 = 2;
public function doFoo(int $flags): void {
if ($flags & self::FLAG_1) {
echo 'Habe Flagge 1';
}
if ($flags & self::FLAG_2) {
echo 'Habe Flagge 2';
}
if ($flags & self::FLAG_3) {
echo 'Habe Flagge 3';
}
}
}
Eine der wichtigsten Änderungen, auf die ich mich freue. In der neuesten Version von PHP werden wir in der Lage sein, Variablen zu markieren als SensitiveParameterValue
. Warum sollten wir?
Die Stack Traces von PHP in Ausnahmen sind sehr nützlich für die Fehlersuche, aber sie ermöglichen Ihnen eine Vorschau der Parameterwerte. Stellen wir uns zum Beispiel vor, PDO Code verwendet, um eine Verbindung zu einer Datenbank herzustellen. Der Debug-Trace würde wie folgt aussehen:
PDOException: SQLSTATE[HY000] [2002] Keine solche Datei oder Verzeichnis in /var/www/html/test.php:3
Stack-Trace:
#0 /var/www/html/test.php(3): PDO->__construct('mysql:host=loca...', 'root', 'password')
#1 {main}
Nach der Verwendung von Annotation #[SensitiveParameter]
zeigt unser Stack-Trace nicht mehr den Wert der Variablen an.
Funktion test(
$foo,
#[SensitiveParameter] $bar,
$baz
) {
throw new Exception('Fehler');
}
test('foo', 'bar', 'baz');
/*
Schwerwiegender Fehler: Ungefangene Exception: Fehler in test.php:8
Stack-Trace:
#0 test.php(11): test('foo', Object(SensitiveParameterValue), 'baz')
#1 {main}
Throw in test.php auf Zeile 8
*/
Als Autor sagt
Die primäre Motivation für diese Änderung ist es, das Abrufen von Name- und Werteigenschaften an Stellen zu ermöglichen, an denen Enum-Objekte nicht erlaubt sind, wie z.B. Array-Schlüssel. Wir könnten an Arrays arbeiten, so dass sie erweitert werden könnten, um Enums oder alle Objekte als Schlüssel zuzulassen, aber das Abrufen von Eigenschaften von Enums ist einfacher.
enum A: Zeichenkette {
Fall B = 'B';
const C = [selbst::B->Wert => selbst::B];
}
Zuvor funktionierten statische Methoden wie folgt:
DateTime::createFromImmutable(): DateTime
DateTimeImmutable::createFromMutable(): DateTimeImmutable
Unter PHP 8.2 wird es geändert in:
DateTime::createFromImmutable(): static
DateTimeImmutable::createFromMutable(): static
Dies ist eine einschneidende Änderung für die Ersteller von Bibliotheken und/oder alle benutzerdefinierten Implementierungen von DateTime.
Das waren zwei Funktionen, die ihren Zweck nicht erfüllten, da sie nur zwischen ISO-8859-1
und UTF-8
. PHP Handbuch empfiehlt die Verwendung von mb_convert_encoding
stattdessen.
Die Empfindlichkeit der Locale wird am besten vom Autor des RFCs beschrieben:
Vor PHP 8.0 wurde das Gebietsschema von PHP über die Umgebung festgelegt. Wenn ein Benutzer Linux installiert, wird er gefragt, in welcher Sprache er es haben möchte. Der Benutzer ist sich der Konsequenzen dieser Entscheidung vielleicht nicht ganz bewusst. Sie legt nicht nur die Sprache der Benutzeroberfläche für die eingebauten Befehle fest, sondern ändert auch die Art und Weise, wie die C-Bibliothek mit Zeichenketten umgeht, grundlegend. Ein Benutzer, der bei der Installation von Linux "Türkisch" auswählt, würde zum Beispiel feststellen, dass Anwendungen, die toupper('i') aufrufen, das gepunktete große I (U+0130, "İ") erhalten.
Im Zeitalter der standardisierten textbasierten Protokolle ist die Anwendung der Groß- und Kleinschreibung in natürlicher Sprache in der Minderheit. Aber selbst wenn der Benutzer die Groß-/Kleinschreibung in natürlicher Sprache umwandeln wollte, wäre es unwahrscheinlich, dass er mit strtolower() Erfolg hätte. Das liegt daran, dass die Zeichenkette Byte für Byte verarbeitet und jedes Byte an tolower() der C-Bibliothek weitergegeben wird. Wenn die Eingabe UTF-8 ist, die bei weitem beliebteste moderne Wahl, wird strtolower() die Zeichenkette verstümmeln und typischerweise ungültiges UTF-8 als Ausgabe produzieren.
PHP 8.0 beachtet die Umgebungsvariablen der Locale nicht mehr. Die Locale ist also immer "C", es sei denn, der Benutzer ruft explizit setlocale() auf. Das bedeutet, dass der größte Teil der rückwärtskompatiblen Änderung bereits hinter uns liegt. Alle Anwendungen, die von der System-Locale abhängig sind, um die Groß-/Kleinschreibung von alten 8-Bit-Zeichensätzen zu konvertieren, wären mit PHP 8.0 nicht mehr möglich gewesen.
Das bedeutet, dass alle unten aufgeführten Funktionen die ASCII-Groß-/Kleinschreibung von PHP.8.2 konvertieren:strtolower
, strtoupper
, stristr
, stripos
, strripos
, lcfirst
, ucfirst
, ucwords
, str_ireplace
In PHP gibt es viele Möglichkeiten, Variablen in Strings einzubetten:
- Direkte Einbettung von Variablen ("$foo")
- Klammern außerhalb der Variablen ("{$foo}")
- Klammern nach dem Dollarzeichen ("${foo}")
- Variable Variablen ("${expr}", entspricht (String) ${expr})
Um Verwirrung und Missbrauch zu vermeiden, werden diese nicht mehr funktionieren:
"Hallo ${Welt}";
Veraltet: Die Verwendung von ${} in Strings ist veraltet
"Hallo ${(Welt)}";
Abgelehnt: Die Verwendung von ${} (variable Variablen) in Strings ist veraltet
Dies sind nicht alle Änderungen, die PHP 8.2 bieten wird. Leider haben wir immer noch keine Unterstützung für generische Typen bekommen, denn laut Nikita würden die monomorphisierten Generics zu viel Performance-Overhead hinzufügen, und verifizierte Generics erfordern viele Änderungen in der gesamten Codebasis. Was jedoch auffällt, ist die Disziplin und Vision der Produkt. Die Änderungen, die in den aufeinanderfolgenden Sprachfassungen vorgenommen wurden, werden immer deutlicher, und der Interessierte wird feststellen, dass PHP geht in die richtige Richtung, sowohl was die Vereinfachung der Syntax als auch die Unterstützung von Neuerungen angeht. Ich erwarte, dass wir bereits im nächsten Jahr aufrufbar
als einen gültigen Typ.