πŸ¦ΈπŸΏβ€β™‚οΈ The GraphQL API for WordPress is now transpiled from PHP 8.0 to 7.1

β€” 9 minute read

Some time ago, I wrote about the art of transpiling PHP code:

Transpiling PHP code enables to use the latest PHP features for development, yet release the plugin with its code converted to an older PHP version for production, as to target a bigger user base.

I spent the past few weeks further tuning this process for the GraphQL API for WordPress plugin.

I'm happy to announce that, from now on, it's required PHP version has been upgraded, to PHP 8.0:

Upgrading to min PHP version 8.0
Upgrading to min PHP version 8.0

Since the plugin can now count on PHP 8.0, I've been able to complete adding a type to all properties for all PHP classes across the code base, now also including union types.

Awesome!

Here is the summary of all the new PHP 8.0 features available when developing the plugin.

New PHP 8.0 features permalink

When developing the GraphQL API plugin, the following PHP 8.0 features are now available:

Let's see an example of each, how they are used in the plugin for development, and what they get transpiled down to when generating graphql-api.zip.

Union types permalink

Code example:

interface CustomPostTypeAPIInterface
{
public function createCustomPost(array $data): string | int | null | Error;
}

Transpiled to:

interface CustomPostTypeAPIInterface
{
public function createCustomPost(array $data)
}

mixed pseudo type permalink

Code example:

interface CMSServiceInterface
{
public function getOption(string $option, mixed $default = false): mixed;
}

Transpiled to:

interface CMSServiceInterface
{
public function getOption(string $option, $default = false);
}

::class magic constant on objects permalink

Code example:

foreach ($directiveResolvers as $directiveResolver) {
$directiveResolverName = $directiveResolver->getDirectiveName();
$this->directiveNameClasses[$directiveResolverName][] = $directiveResolver::class;
}

Transpiled to:

foreach ($directiveResolvers as $directiveResolver) {
$directiveResolverName = $directiveResolver->getDirectiveName();
$this->directiveNameClasses[$directiveResolverName][] = get_class($directiveResolver);
}

match expressions permalink

Code example:

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;
}

Transpiled to:

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 only by type permalink

Code example:

try {
// ...
} catch (InvalidArgumentException) {
return sprintf(
'<p>%s</p>',
\__('Oops, the documentation for this module is not available', 'graphql-api')
);
}

Transpiled to:

try {
// ...
} catch (InvalidArgumentException $exception) {
return sprintf(
'<p>%s</p>',
\__('Oops, the documentation for this module is not available', 'graphql-api')
);
}

Null-safe operator permalink

Code example:

public function getSchemaDirectiveDeprecationDescription(TypeResolverInterface $typeResolver): ?string
{
return $this->getSchemaDefinitionResolver($typeResolver)?->getSchemaDirectiveDeprecationDescription($typeResolver);
}

Transpiled to:

public function getSchemaDirectiveDeprecationDescription(TypeResolverInterface $typeResolver): ?string
{
return $this->getSchemaDefinitionResolver($typeResolver) ? $this->getSchemaDefinitionResolver($typeResolver)->getSchemaDirectiveDeprecationDescription($typeResolver) : null;
}

Class constructor property promotion permalink

Code example:

abstract class AbstractEndpointResolver
{
function __construct(protected EndpointHelpers $endpointHelpers)
{
}
}

Transpiled to:

 abstract class AbstractEndpointResolver
{
/**
* @var \GraphQLAPI\GraphQLAPI\Services\Helpers\EndpointHelpers
*/

protected $endpointHelpers;

function __construct(EndpointHelpers $endpointHelpers)
{
$this->endpointHelpers = $endpointHelpers;
}
}

Trailing commas in parameter lists and closure use lists permalink

Code example:

public function resolveFieldTypeResolverClass(TypeResolverInterface $typeResolver, string $fieldName): ?string
{
switch ($fieldName) {
case 'accessControlLists':
return CustomPostTypeResolver::class;
}

return parent::resolveFieldTypeResolverClass(
$typeResolver,
$fieldName,
);
}

Transpiled to:

public function resolveFieldTypeResolverClass(TypeResolverInterface $typeResolver, string $fieldName): ?string
{
switch ($fieldName) {
case 'accessControlLists':
return CustomPostTypeResolver::class;
}

return parent::resolveFieldTypeResolverClass($typeResolver, $fieldName);
}

Share on 🐦 Twitter | πŸ‘ŽπŸΎ Facebook