🦸🏿♂️ Gato GraphQL est maintenant transpilé de PHP 8.0 à 7.1
Il y a quelque temps, j'ai écrit sur l'art de transpiler du code PHP :
- 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
Transpiler du code PHP permet d'utiliser les dernières fonctionnalités de PHP pour le développement, tout en publiant le plugin avec son code converti vers une ancienne version de PHP pour la production, afin de cibler une base d'utilisateurs plus large.
J'ai passé les dernières semaines à affiner davantage ce processus pour le plugin Gato GraphQL.
Je suis heureux d'annoncer que, désormais, la version PHP requise a été mise à niveau vers PHP 8.0 :

Comme le plugin peut désormais compter sur PHP 8.0, j'ai pu terminer l'ajout d'un type à toutes les propriétés pour toutes les classes PHP dans l'ensemble du code, en incluant maintenant également les union types.
Formidable !
Voici le résumé de toutes les nouvelles fonctionnalités de PHP 8.0 disponibles lors du développement du plugin.
Nouvelles fonctionnalités de PHP 8.0
Lors du développement de Gato GraphQL, les fonctionnalités PHP 8.0 suivantes sont désormais disponibles :
- Union types
- Pseudo-type
mixed - Type de retour
static - Constante magique
::classsur les objets - Expressions
match catchexceptions par type uniquement- Opérateur Null-safe
- Promotion des propriétés dans le constructeur de classe
- Virgules de fin dans les listes de paramètres et les listes
usede closures
Voyons un exemple de chacune, comment elles sont utilisées dans le plugin pour le développement, et en quoi elles sont transpilées lors de la génération de graphql-api.zip.
Union types
interface CustomPostTypeAPIInterface
{
public function createCustomPost(array $data): string | int | null | Error;
}Transpilé en :
interface CustomPostTypeAPIInterface
{
public function createCustomPost(array $data)
}Pseudo-type mixed
interface CMSServiceInterface
{
public function getOption(string $option, mixed $default = false): mixed;
}Transpilé en :
interface CMSServiceInterface
{
public function getOption(string $option, $default = false);
}Constante magique ::class sur les objets
foreach ($directiveResolvers as $directiveResolver) {
$directiveResolverName = $directiveResolver->getDirectiveName();
$this->directiveNameClasses[$directiveResolverName][] = $directiveResolver::class;
}Transpilé en :
foreach ($directiveResolvers as $directiveResolver) {
$directiveResolverName = $directiveResolver->getDirectiveName();
$this->directiveNameClasses[$directiveResolverName][] = get_class($directiveResolver);
}Expressions match
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;
}Transpilé en :
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 exceptions par type uniquement
try {
// ...
} catch (InvalidArgumentException) {
return sprintf(
'<p>%s</p>',
\__('Oops, the documentation for this module is not available', 'graphql-api')
);
}Transpilé en :
try {
// ...
} catch (InvalidArgumentException $exception) {
return sprintf(
'<p>%s</p>',
\__('Oops, the documentation for this module is not available', 'graphql-api')
);
}Opérateur Null-safe
public function getSchemaDirectiveDeprecationDescription(TypeResolverInterface $typeResolver): ?string
{
return $this->getSchemaDefinitionResolver($typeResolver)?->getSchemaDirectiveDeprecationDescription($typeResolver);
}Transpilé en :
public function getSchemaDirectiveDeprecationDescription(TypeResolverInterface $typeResolver): ?string
{
return $this->getSchemaDefinitionResolver($typeResolver) ? $this->getSchemaDefinitionResolver($typeResolver)->getSchemaDirectiveDeprecationDescription($typeResolver) : null;
}Promotion des propriétés dans le constructeur de classe
abstract class AbstractEndpointResolver
{
function __construct(protected EndpointHelpers $endpointHelpers)
{
}
}Transpilé en :
abstract class AbstractEndpointResolver
{
/**
* @var \GraphQLAPI\GraphQLAPI\Services\Helpers\EndpointHelpers
*/
protected $endpointHelpers;
function __construct(EndpointHelpers $endpointHelpers)
{
$this->endpointHelpers = $endpointHelpers;
}
}Virgules de fin dans les listes de paramètres et les listes use de closures
public function resolveFieldTypeResolverClass(TypeResolverInterface $typeResolver, string $fieldName): ?string
{
switch ($fieldName) {
case 'accessControlLists':
return CustomPostTypeResolver::class;
}
return parent::resolveFieldTypeResolverClass(
$typeResolver,
$fieldName,
);
}Transpilé en :
public function resolveFieldTypeResolverClass(TypeResolverInterface $typeResolver, string $fieldName): ?string
{
switch ($fieldName) {
case 'accessControlLists':
return CustomPostTypeResolver::class;
}
return parent::resolveFieldTypeResolverClass($typeResolver, $fieldName);
}