SOLID
Gato GraphQL volgt de SOLID-aanpak voor de softwarearchitectuur, waarbij verschillende entiteiten worden ingezet voor verschillende verantwoordelijkheden, zodat de code onderhoudbaar, uitbreidbaar en begrijpelijk blijft.
Zo wordt de gebruikersentiteit al door de plugin geleverd. Het type User wordt geleverd via deze code:
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;
}
}De type resolver laadt objecten niet rechtstreeks uit de database, maar delegeert deze taak aan een TypeDataLoader-object (in het bovenstaande voorbeeld, van klasse UserTypeDataLoader).
Het toevoegen van velden username, email en url aan het type User gebeurt via een FieldResolver-object met deze 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;
}
}Zoals je kunt zien, is de definitie van een veld voor het GraphQL-schema en de verwerking ervan opgesplitst in een reeks functies:
getSchemaFieldDescriptiongetSchemaFieldTyperesolveValue
Andere functies zijn onder meer:
getSchemaFieldArgs: om de veldargumenten te declareren (inclusief naam, beschrijving, type en of ze verplicht zijn)isSchemaFieldResponseNonNullable: om aan te geven of een veld non-nullable isgetImplementedInterfaceClasses: om de resolvers te definiëren voor interfaces die door de velden worden geïmplementeerdresolveFieldTypeResolverClass: om de type resolver te definiëren wanneer het veld een verbinding isresolveFieldMutationResolverClass: om de resolver te definiëren wanneer het veld mutations uitvoert
Deze code is leesbaarder dan wanneer alle functionaliteit via één enkele functie of een configuratiearray wordt afgehandeld, waardoor het eenvoudiger is om de resolvers te implementeren en te onderhouden.