Blog

🦸🏿‍♂️ Gato GraphQL agora é transpilado de PHP 8.0 para 7.1

Leonardo Losoviz
Por Leonardo Losoviz ·

Há algum tempo, escrevi sobre a arte de transpilar código PHP:

Transpilar código PHP permite usar os recursos mais recentes do PHP para o desenvolvimento, mas ainda assim publicar o plugin com o código convertido para uma versão mais antiga do PHP para produção, de forma a atingir uma base de usuários maior.

Passei as últimas semanas refinando ainda mais esse processo para o plugin Gato GraphQL.

Tenho o prazer de anunciar que, a partir de agora, a versão mínima de PHP exigida foi atualizada para PHP 8.0:

Atualização para a versão mínima PHP 8.0

Como o plugin agora pode contar com PHP 8.0, consegui concluir a adição de um tipo a todas as propriedades de todas as classes PHP em toda a base de código, incluindo agora também os union types.

Incrível!

Aqui está o resumo de todos os novos recursos do PHP 8.0 disponíveis ao desenvolver o plugin.

Novos recursos do PHP 8.0

Ao desenvolver o Gato GraphQL, os seguintes recursos do PHP 8.0 estão agora disponíveis:

Vamos ver um exemplo de cada um, como são usados no plugin para o desenvolvimento e em que são transpilados ao gerar o graphql-api.zip.

Union types

Exemplo de código:

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

Transpilado para:

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

Pseudotipo mixed

Exemplo de código:

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

Transpilado para:

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

Constante mágica ::class em objetos

Exemplo de código:

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

Transpilado para:

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

Expressões match

Exemplo de código:

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

Transpilado para:

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 de exceções somente por tipo

Exemplo de código:

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

Transpilado para:

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

Operador Null-safe

Exemplo de código:

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

Transpilado para:

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

Promoção de propriedades no construtor de classe

Exemplo de código:

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

Transpilado para:

 abstract class AbstractEndpointResolver
 {
  /**
   * @var \GraphQLAPI\GraphQLAPI\Services\Helpers\EndpointHelpers
   */
  protected $endpointHelpers;
 
  function __construct(EndpointHelpers $endpointHelpers)
  {
    $this->endpointHelpers = $endpointHelpers;
  }
}

Vírgulas finais em listas de parâmetros e listas use de closures

Exemplo de código:

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

Transpilado para:

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

Assine nossa newsletter

Fique por dentro de todas as atualizações do Gato GraphQL.