SOLID
Gato GraphQL folgt dem SOLID-Ansatz für die Softwarearchitektur und stellt verschiedene Entitäten bereit, die unterschiedliche Verantwortlichkeiten übernehmen, um den Code wartbar, erweiterbar und verständlich zu machen.
So wird die Benutzerentität bereits vom Plugin bereitgestellt. Der Typ User wird über diesen Code zur Verfügung gestellt:
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;
}
}Der Type Resolver lädt die Objekte nicht direkt aus der Datenbank, sondern delegiert diese Aufgabe an ein TypeDataLoader-Objekt (im obigen Beispiel an die Klasse UserTypeDataLoader).
Das Hinzufügen der Felder username, email und url zum Typ User erfolgt über ein FieldResolver-Objekt mit diesem Code:
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;
}
}Wie zu erkennen ist, wurde die Definition eines Feldes für das GraphQL-Schema sowie dessen Auflösung auf eine Vielzahl von Funktionen aufgeteilt:
getSchemaFieldDescriptiongetSchemaFieldTyperesolveValue
Weitere Funktionen umfassen:
getSchemaFieldArgs: zum Deklarieren der Feldargumente (einschließlich Name, Beschreibung, Typ und ob sie erforderlich sind)isSchemaFieldResponseNonNullable: um anzugeben, ob ein Feld non-nullable istgetImplementedInterfaceClasses: zum Definieren der Resolver für Interfaces, die von den Feldern implementiert werdenresolveFieldTypeResolverClass: zum Definieren des Type Resolvers, wenn das Feld eine Verbindung istresolveFieldMutationResolverClass: zum Definieren des Resolvers, wenn das Feld Mutations ausführt
Dieser Code ist lesbarer als wenn die gesamte Funktionalität über eine einzelne Funktion oder ein Konfigurations-Array abgewickelt wird, was die Implementierung und Pflege der Resolver erheblich vereinfacht.