SOLID
Gato GraphQL segue l'approccio SOLID per l'architettura del software, fornendo diverse entità per gestire diverse responsabilità , in modo da rendere il codice manutenibile, estensibile e comprensibile.
Ecco come l'entità utente è già fornita dal plugin. Il tipo User è fornito tramite questo codice:
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;
}
}Il type resolver non carica direttamente gli oggetti dal database, ma delega questo compito a un oggetto TypeDataLoader (nell'esempio sopra, dalla classe UserTypeDataLoader).
L'aggiunta dei campi username, email e url al tipo User avviene tramite un oggetto FieldResolver con questo codice:
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;
}
}Come si può osservare, la definizione di un campo per lo schema GraphQL, e la sua risoluzione, è stata suddivisa in una moltitudine di funzioni:
getSchemaFieldDescriptiongetSchemaFieldTyperesolveValue
Altre funzioni includono:
getSchemaFieldArgs: per dichiarare gli argomenti del campo (inclusi il loro nome, descrizione, tipo, e se sono obbligatori o meno)isSchemaFieldResponseNonNullable: per indicare se un campo è non nullablegetImplementedInterfaceClasses: per definire i resolver per le interfacce implementate dai campiresolveFieldTypeResolverClass: per definire il type resolver quando il campo è una connessioneresolveFieldMutationResolverClass: per definire il resolver quando il campo esegue delle mutations
Questo codice è più leggibile rispetto a quando tutte le funzionalità sono soddisfatte tramite un'unica funzione, o tramite un array di configurazione, rendendo così più facile implementare e mantenere i resolver.