Kiến trúc
Kiến trúcSOLID

SOLID

Gato GraphQL tuân theo phương pháp SOLID cho kiến trúc phần mềm, cung cấp các thực thể khác nhau để xử lý các trách nhiệm khác nhau, nhằm làm cho code dễ bảo trì, mở rộng và dễ hiểu.

Đây là cách thực thể người dùng đã được cung cấp sẵn bởi plugin. Kiểu User được cung cấp thông qua đoạn code này:

class UserTypeResolver extends AbstractTypeResolver
{
  public function getTypeName(): string
  {
    return 'User';
  }
 
  public function getSchemaTypeDescription(): ?string
  {
    return $this->translationAPI->__('Representation of a user', "users");
  }
 
  public function getID(object $user)
  {
    return $this->usersAPI->getUserId($user);
  }
 
  public function getTypeDataLoaderClass(): string
  {
    return UserTypeDataLoader::class;
  }
}

Type resolver không trực tiếp tải các đối tượng từ cơ sở dữ liệu, mà thay vào đó ủy thác tác vụ này cho một đối tượng TypeDataLoader (trong ví dụ trên, từ lớp UserTypeDataLoader).

Việc thêm các trường username, emailurl vào kiểu User được thực hiện thông qua một đối tượng FieldResolver với đoạn code này:

class UserFieldResolver extends AbstractDBDataFieldResolver
{
  public static function getClassesToAttachTo(): array
  {
    return [
      UserTypeResolver::class,
    ];
  }
 
  public static function getFieldNamesToResolve(): array
  {
    return [
      'username',
      'email',
      'url',
    ];
  }
 
  public function getSchemaFieldDescription(
    TypeResolverInterface $typeResolver,
    string $fieldName
  ): ?string {
    $descriptions = [
      'username' => $this->translationAPI->__("User's username handle", "users"),
      'email' => $this->translationAPI->__("User's email", "users"),
      'url' => $this->translationAPI->__("URL of the user's profile in the website", "users"),
    ];
    return $descriptions[$fieldName];
  }
 
  public function getSchemaFieldType(
    TypeResolverInterface $typeResolver,
    string $fieldName
  ): ?string {
    $types = [
      'username' => SchemaDefinition::TYPE_STRING,
      'email' => SchemaDefinition::TYPE_EMAIL,
      'url' => SchemaDefinition::TYPE_URL,
    ];
    return $types[$fieldName];
  }
 
  public function resolveValue(
    TypeResolverInterface $typeResolver,
    object $user,
    string $fieldName,
    array $fieldArgs = []
  ) {
    switch ($fieldName) {
      case 'username':
        return $this->usersAPI->getUserLogin($user);
 
      case 'email':
        return $this->usersAPI->getUserEmail($user);
 
      case 'url':
        return $this->usersAPI->getUserURL($user);
    }
 
    return null;
  }
}

Như có thể thấy, định nghĩa của một trường cho schema GraphQL, và quá trình phân giải của nó, đã được tách thành nhiều hàm:

  • getSchemaFieldDescription
  • getSchemaFieldType
  • resolveValue

Các hàm khác bao gồm:

Code này dễ đọc hơn so với khi tất cả chức năng được thực hiện thông qua một hàm duy nhất, hoặc thông qua một mảng cấu hình, do đó giúp việc triển khai và bảo trì các resolver trở nên dễ dàng hơn.