🦸🏿♂️ Gato GraphQL wird jetzt von PHP 8.0 auf 7.1 transpiliert
Vor einiger Zeit habe ich über die Kunst des Transpilierens von PHP-Code geschrieben:
- Transpiling PHP code from 8.0 to 7.x via Rector
- Coding in PHP 7.4 and deploying to 7.1 via Rector and GitHub Actions
Das Transpilieren von PHP-Code ermöglicht es, die neuesten PHP-Funktionen für die Entwicklung zu nutzen und das Plugin dennoch mit auf eine ältere PHP-Version konvertiertem Code für die Produktion zu veröffentlichen, um eine größere Nutzerbasis anzusprechen.
Ich habe die letzten Wochen damit verbracht, diesen Prozess für das Plugin Gato GraphQL weiter zu verfeinern.
Ich freue mich, ankündigen zu können, dass die erforderliche PHP-Version ab sofort auf PHP 8.0 angehoben wurde:

Da das Plugin nun auf PHP 8.0 zählen kann, konnte ich das Hinzufügen eines Typs zu allen Eigenschaften für alle PHP-Klassen im gesamten Codebase abschließen, einschließlich Union Types.
Großartig!
Hier ist die Zusammenfassung aller neuen PHP-8.0-Funktionen, die bei der Entwicklung des Plugins verfügbar sind.
Neue PHP-8.0-Funktionen
Bei der Entwicklung von Gato GraphQL stehen jetzt folgende PHP-8.0-Funktionen zur Verfügung:
- Union types
- Pseudo-Typ
mixed - Rückgabetyp
static - Magische Konstante
::classauf Objekten match-Ausdrückecatch-Ausnahmen nur nach Typ- Null-safe-Operator
- Promotion von Klassen-Konstruktor-Eigenschaften
- Abschließende Kommas in Parameterlisten und
use-Listen von Closures
Sehen wir uns jeweils ein Beispiel an, wie sie im Plugin für die Entwicklung verwendet werden und wohin sie beim Generieren von graphql-api.zip transpiliert werden.
Union types
interface CustomPostTypeAPIInterface
{
public function createCustomPost(array $data): string | int | null | Error;
}Transpiliert zu:
interface CustomPostTypeAPIInterface
{
public function createCustomPost(array $data)
}Pseudo-Typ mixed
interface CMSServiceInterface
{
public function getOption(string $option, mixed $default = false): mixed;
}Transpiliert zu:
interface CMSServiceInterface
{
public function getOption(string $option, $default = false);
}Magische Konstante ::class auf Objekten
foreach ($directiveResolvers as $directiveResolver) {
$directiveResolverName = $directiveResolver->getDirectiveName();
$this->directiveNameClasses[$directiveResolverName][] = $directiveResolver::class;
}Transpiliert zu:
foreach ($directiveResolvers as $directiveResolver) {
$directiveResolverName = $directiveResolver->getDirectiveName();
$this->directiveNameClasses[$directiveResolverName][] = get_class($directiveResolver);
}match-Ausdrücke
public function getSchemaFieldType(TypeResolverInterface $typeResolver, string $fieldName): ?string
{
$ret = match($fieldName) {
'accessControlLists' => TypeCastingHelpers::makeArray(SchemaDefinition::TYPE_ID),
'cacheControlLists' => TypeCastingHelpers::makeArray(SchemaDefinition::TYPE_ID),
'fieldDeprecationLists' => TypeCastingHelpers::makeArray(SchemaDefinition::TYPE_ID),
'schemaConfigurations' => TypeCastingHelpers::makeArray(SchemaDefinition::TYPE_ID),
default => parent::getSchemaFieldType($typeResolver, $fieldName),
};
return $ret;
}Transpiliert zu:
public function getSchemaFieldType(TypeResolverInterface $typeResolver, string $fieldName): ?string
{
switch ($fieldName) {
case 'accessControlLists':
$ret = TypeCastingHelpers::makeArray(SchemaDefinition::TYPE_ID);
break;
case 'cacheControlLists':
$ret = TypeCastingHelpers::makeArray(SchemaDefinition::TYPE_ID);
break;
case 'fieldDeprecationLists':
$ret = TypeCastingHelpers::makeArray(SchemaDefinition::TYPE_ID);
break;
case 'schemaConfigurations':
$ret = TypeCastingHelpers::makeArray(SchemaDefinition::TYPE_ID);
break;
default:
$ret = parent::getSchemaFieldType($typeResolver, $fieldName);
break;
}
return $ret;
}catch-Ausnahmen nur nach Typ
try {
// ...
} catch (InvalidArgumentException) {
return sprintf(
'<p>%s</p>',
\__('Oops, the documentation for this module is not available', 'graphql-api')
);
}Transpiliert zu:
try {
// ...
} catch (InvalidArgumentException $exception) {
return sprintf(
'<p>%s</p>',
\__('Oops, the documentation for this module is not available', 'graphql-api')
);
}Null-safe-Operator
public function getSchemaDirectiveDeprecationDescription(TypeResolverInterface $typeResolver): ?string
{
return $this->getSchemaDefinitionResolver($typeResolver)?->getSchemaDirectiveDeprecationDescription($typeResolver);
}Transpiliert zu:
public function getSchemaDirectiveDeprecationDescription(TypeResolverInterface $typeResolver): ?string
{
return $this->getSchemaDefinitionResolver($typeResolver) ? $this->getSchemaDefinitionResolver($typeResolver)->getSchemaDirectiveDeprecationDescription($typeResolver) : null;
}Promotion von Klassen-Konstruktor-Eigenschaften
abstract class AbstractEndpointResolver
{
function __construct(protected EndpointHelpers $endpointHelpers)
{
}
}Transpiliert zu:
abstract class AbstractEndpointResolver
{
/**
* @var \GraphQLAPI\GraphQLAPI\Services\Helpers\EndpointHelpers
*/
protected $endpointHelpers;
function __construct(EndpointHelpers $endpointHelpers)
{
$this->endpointHelpers = $endpointHelpers;
}
}Abschließende Kommas in Parameterlisten und use-Listen von Closures
public function resolveFieldTypeResolverClass(TypeResolverInterface $typeResolver, string $fieldName): ?string
{
switch ($fieldName) {
case 'accessControlLists':
return CustomPostTypeResolver::class;
}
return parent::resolveFieldTypeResolverClass(
$typeResolver,
$fieldName,
);
}Transpiliert zu:
public function resolveFieldTypeResolverClass(TypeResolverInterface $typeResolver, string $fieldName): ?string
{
switch ($fieldName) {
case 'accessControlLists':
return CustomPostTypeResolver::class;
}
return parent::resolveFieldTypeResolverClass($typeResolver, $fieldName);
}