Named Arguments werden mit der Veröffentlichung von der Version 8 Einzug in die PHP-Welt halten und das Leben der Entwickler vereinfachen. Doch neben der Euphorie gibt es vor allem einen Vorbehalt bei dem neuen Feature – genau wie bereits erste Lösungsansätze.
Named Arguments sind eines der großen neuen Features der lang ersehnten 8. Major Version von PHP. In die Vorfreude auf das anstehende Release haben sich allerdings auch einige Bedenken bezüglich der Neuerungen gemischt. An Lösungen wird bereits gearbeitet – wie etwa im Falle des Tools Psalm und den bereits erwähnten Named Arguments. Nehmen wir an, wir haben eine Schnittstelle zu einer bestehenden Bibliothek eines Drittanbieters und wollen diese abfragen. In PHP 7 ist der Code einfach:
interface IQueryable {
public function fetchValue(string $sqlString, bool $cache);
}
class MySqlQueryable implements IQueryable {
public function fetchValue(string $queryString, bool $cache)
{
echo $queryString;
// some code
}
}
function executeSQL(IQueryable $queryable) {
return $queryable->fetchValue(
"SELECT count(*) from foo",
true
);
}
executeSql(new MySqlQueryable());
In PHP 8 wird der gleiche Code einwandfrei funktionieren. Es sei denn, wir entscheiden uns, die Methode mit Named Arguments aufzurufen, wobei wir auf einen fatalen Fehler stoßen werden:
function executeSQL(IQueryable $queryable) {
return $queryable->fetchValue(
sqlString: "SELECT count(*) from foo",
cache: true
);
}
// Fatal Error: Unknown named parameter $sqlString
Das liegt daran, dass die Schnittstelle zwar einen $sqlString
-Parameter hat, die eigentliche implementierende Klasse jedoch nicht (sie heißt stattdessen $queryString
). PHP weiß somit nicht, was zu tun ist. Wir könnten das Problem beheben, indem wir $queryString
in $sqlString
umbenennen.
In der neuesten Version von Psalm werden Sie auf diese Abweichungen der Parameternamen mit einem ParamNameMismatch
-Problem hingewiesen, so dass Sie leicht erkennen können, welche Methoden nicht mit dem Aufruf von Named Agruments kompatibel sind. Wenn Sie sie alle in einem Rutsch beheben möchten, kann Psalm das tun – führen Sie dazu einfach
vendor/bin/psalm --alter --issues=ParamNameMismatch
aus. Das obige Beispiel wird folgendes Resultat ausgeben:
interface IQueryable {
public function fetchValue(string $sqlString, bool $cache);
}
class MySqlQueryable implements IQueryable {
public function fetchValue(string $sqlString, bool $cache)
{
echo $sqlString;
// some code
}
}
Wenn Sie eine so große Änderung nicht durchführen möchten oder wenn Sie ein Library Maintainer sind, haben Sie einige alternative Möglichkeiten.
Wenn Sie die uneingeschränkte Kontrolle darüber besitzen, wer ihren Code wie verwendet, möchten sie eventuell ein generelles Verbot Verbot für die Verwendung von Named Arguments beim Aufruf von Methoden implementieren. Falls sie dabei Psalm verwenden, ist das mit allowNamedArgumentCalls="false"
-Flag in Ihrer Psalm-Konfiguration möglich. Wenn dieses Flag hinzugefügt wird, erlaubt Psalm nicht übereinstimmende Parameternamen für jede Methode, bei der die Schnittstelle/übergeordnete Klasse in Ihrem Code enthalten ist.
Wenn Sie keine vollständige Kontrolle darüber haben, wie Ihr Code aufgerufen wird, können die Dinge allerdings etwas knifflig werden. Wenn sie ein öffentliches API verwenden, wie etwa
interface IQueryable {
function fetchValue(string $sqlString, bool $cache);
}
ist es nicht mehr länger möglich, den Namen des Parameters in $queryString
zu ändern, sonst verlieren Sie jeden Benutzer des APIs, der diese Methode mit Named Arguments aufruft.
Psalm (gefolgt von weiteren Tools in naher Zukunft) unterstützt aus diesem Grund die DocBlock-Annotation @no-named-arguments
, die zu Methoden hinzugefügt werden kann:
interface IQueryable {
/** @no-named-arguments */
function fetchValue(string $sqlString);
}
Sobald Psalm die Unterstützung für den Aufruf von Methoden mit Named Arguments gewährleistet, werden diese Aufrufe für jede Methode mit dieser Annotation verboten. Weiterhin ermöglicht es den Verwaltern von Libraries, Parameter umzubenennen, ohne die Rückwärtskompatibilität für jeden, der statische Analysewerkzeuge verwendet, zu beeinträchtigen. Es ist eine etwas lockerere Garantie, aber es ist das Jahr 2020 und wir müssen uns alle zunächst einmal damit abfinden.
Psalm unterstützt auch ein zweites Konfigurationsflag allowInternalNamedArgumentCalls="false"
. Dies erlaubt es Library Maintainern, übereinstimmende Parameter-Namen zu garantieren – mit Ausnahme von internen Klassen und Interfaces, wo es freisteht, Dinge zu ändern.
Da dieses Flag zur Psalm-Konfiguration hinzugefügt wurde, ist folgendes nun erlaubt:
/** @internal */
interface IQueryable {
public function fetchValue(string $sqlString, bool $cache);
}
/** @internal */
class MySqlQueryable implements IQueryable {
public function fetchValue(string $queryString, bool $cache)
{
// some code
}
}
Es bleibt zu hoffen, dass diese Optionen einige Bedenken hinsichtlich der Einführung der genannten Argumente zerstreuen werden. Es wird weitere Aktualisierungen geben, sobald Psalm Unterstützung für die Funktionen von PHP 8 hinzufügt.