Blog

🦸🏿‍♂️ Gato GraphQL hiện được biên dịch từ PHP 8.0 xuống 7.1

Leonardo Losoviz
Bởi Leonardo Losoviz ·

Một thời gian trước, tôi đã viết về nghệ thuật biên dịch chéo (transpile) mã PHP:

Biên dịch chéo mã PHP cho phép sử dụng các tính năng PHP mới nhất trong quá trình phát triển, nhưng vẫn phát hành plugin với mã đã được chuyển đổi sang phiên bản PHP cũ hơn cho môi trường production, nhằm tiếp cận được nhiều người dùng hơn.

Tôi đã dành vài tuần qua để tinh chỉnh thêm quy trình này cho plugin Gato GraphQL.

Tôi vui mừng thông báo rằng, từ nay, phiên bản PHP yêu cầu đã được nâng cấp lên PHP 8.0:

Nâng cấp lên phiên bản PHP tối thiểu 8.0

Vì plugin hiện có thể dựa vào PHP 8.0, tôi đã hoàn thành việc bổ sung kiểu dữ liệu cho tất cả các thuộc tính trong tất cả các lớp PHP trên toàn bộ codebase, bao gồm cả union types.

Tuyệt vời!

Dưới đây là tóm tắt tất cả các tính năng PHP 8.0 mới có sẵn khi phát triển plugin.

Các tính năng mới của PHP 8.0

Khi phát triển Gato GraphQL, các tính năng PHP 8.0 sau đây hiện đã có sẵn:

Hãy xem ví dụ về từng tính năng, cách chúng được sử dụng trong plugin khi phát triển, và chúng được biên dịch chéo thành gì khi tạo graphql-api.zip.

Union types

Ví dụ code:

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

Biên dịch chéo thành:

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

Kiểu giả mixed

Ví dụ code:

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

Biên dịch chéo thành:

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

Hằng số ma thuật ::class trên các đối tượng

Ví dụ code:

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

Biên dịch chéo thành:

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

Biểu thức match

Ví dụ code:

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

Biên dịch chéo thành:

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 ngoại lệ chỉ theo kiểu

Ví dụ code:

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

Biên dịch chéo thành:

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

Toán tử Null-safe

Ví dụ code:

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

Biên dịch chéo thành:

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

Khởi tạo thuộc tính trong constructor của lớp

Ví dụ code:

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

Biên dịch chéo thành:

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

Dấu phẩy cuối trong danh sách tham số và danh sách use của closure

Ví dụ code:

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

Biên dịch chéo thành:

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

Đăng ký nhận bản tin của chúng tôi

Cập nhật tất cả những điều mới từ Gato GraphQL.