Ein in PHP geschriebener GraphQL-Client, der sehr einfache, aber leistungsstarke Abfragegeneratorklassen bereitstellt, die die Interaktion mit einem GraphQL-Server sehr einfach machen.
Es gibt drei Hauptmöglichkeiten, dieses Paket zum Generieren Ihrer GraphQL-Abfragen zu verwenden:
Query
Objekte dynamisch generiert werden können. Das Design eignet sich für Fälle, in denen eine Abfrage dynamisch erstellt wird.Führen Sie den folgenden Befehl aus, um das Paket mit Composer zu installieren:
$ composer require gmostafa/php-graphql-client
Um den Aufwand zu vermeiden, Abfragen schreiben zu müssen und einfach mit PHP-Objekten zu interagieren, die aus Ihrem API-Schema generiert wurden, besuchen Sie das PHP GraphQL OQM-Repository
$ gql = ( new Query ( ' companies ' ))
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
Diese einfache Abfrage ruft alle Unternehmen ab, deren Namen und Seriennummern angezeigt werden.
Die im vorherigen Beispiel bereitgestellte Abfrage wird in der „Kurzform“ dargestellt. Die Kurzform erfordert das Schreiben einer reduzierten Anzahl von Codezeilen, was den Prozess des Schreibens von Abfragen beschleunigt. Unten finden Sie ein Beispiel für das vollständige Formular für genau dieselbe Abfrage, die im vorherigen Beispiel geschrieben wurde.
$ gql = ( new Query ())
-> setSelectionSet (
[
( new Query ( ' companies ' ))
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
)
]
);
Wie im Beispiel zu sehen ist, ist die Kurzform einfacher zu lesen und zu schreiben und wird im Allgemeinen der Vollform vorgezogen.
Die vollständige Form sollte nicht verwendet werden, es sei denn, die Abfrage kann nicht in der Kurzform dargestellt werden, die nur einen Fall hat, wenn wir mehrere Abfragen im selben Objekt ausführen möchten.
$ gql = ( new Query ())
-> setSelectionSet (
[
( new Query ( ' companies ' ))
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
),
( new Query ( ' countries ' ))
-> setSelectionSet (
[
' name ' ,
' code ' ,
]
)
]
);
Diese Abfrage ruft alle Unternehmen und Länder ab und zeigt jeweils einige Datenfelder an. Grundsätzlich werden zwei (oder bei Bedarf mehr) unabhängige Abfragen in einem Abfrageobjektumschlag ausgeführt.
Das Schreiben mehrerer Abfragen erfordert das Schreiben des Abfrageobjekts in vollständiger Form, um jede Abfrage als Unterfeld unter dem übergeordneten Abfrageobjekt darzustellen.
$ gql = ( new Query ( ' companies ' ))
-> setSelectionSet (
[
' name ' ,
' serialNumber ' ,
( new Query ( ' branches ' ))
-> setSelectionSet (
[
' address ' ,
( new Query ( ' contracts ' ))
-> setSelectionSet ([ ' date ' ])
]
)
]
);
Diese Abfrage ist komplexer und ruft nicht nur Skalarfelder, sondern auch Objektfelder ab. Diese Abfrage gibt alle Unternehmen mit ihren Namen und Seriennummern sowie für jedes Unternehmen alle seine Filialen mit der Filialadresse zurück und ruft für jede Adresse alle an diese Adresse gebundenen Verträge mit ihren Daten ab.
$ gql = ( new Query ( ' companies ' ))
-> setArguments ([ ' name ' => ' Tech Co. ' , ' first ' => 3 ])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
Diese Abfrage ruft nicht alle Unternehmen durch Hinzufügen von Argumenten ab. Diese Abfrage ruft die ersten drei Unternehmen mit dem Namen „Tech Co.“ ab und zeigt deren Namen und Seriennummern an.
$ gql = ( new Query ( ' companies ' ))
-> setArguments ([ ' serialNumbers ' => [ 159 , 260 , 371 ]])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
Diese Abfrage ist ein Sonderfall der Argumentabfrage. In diesem Beispiel ruft die Abfrage nur die Unternehmen mit der Seriennummer 159, 260 und 371 ab und zeigt den Namen und die Seriennummer an.
$ gql = ( new Query ( ' companies ' ))
-> setArguments ([ ' filter ' => new RawObject ( ' {name_starts_with: "Face"} ' )])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
Diese Abfrage ist ein weiterer Sonderfall der Argumentabfrage. In diesem Beispiel legen wir einen benutzerdefinierten Eingabeobjekt-„Filter“ mit einigen Werten fest, um die zurückgegebenen Unternehmen einzuschränken. Wir setzen den Filter „name_starts_with“ mit dem Wert „Face“. Diese Abfrage ruft nur die Unternehmen ab, deren Namen mit der Phrase „Face“ beginnen.
Die erstellte RawObject-Klasse wird verwendet, um die Zeichenfolge unverändert in die Abfrage einzufügen. Welche Zeichenfolge auch immer in den RawObject-Konstruktor eingegeben wird, wird unverändert in die Abfrage eingefügt, ohne dass eine benutzerdefinierte Formatierung erfolgt, die normalerweise von der Abfrageklasse vorgenommen wird.
$ gql = ( new Query ( ' companies ' ))
-> setVariables (
[
new Variable ( ' name ' , ' String ' , true ),
new Variable ( ' limit ' , ' Int ' , false , 5 )
]
)
-> setArguments ([ ' name ' => ' $name ' , ' first ' => ' $limit ' ])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
Diese Abfrage zeigt, wie Variablen in diesem Paket verwendet werden können, um dynamische Anforderungen zu ermöglichen, die durch GraphQL-Standards ermöglicht werden.
Die Variable-Klasse ist eine unveränderliche Klasse, die eine Variable in GraphQL-Standards darstellt. Sein Konstruktor erhält 4 Argumente:
$ gql = ( new Query ())
-> setSelectionSet (
[
( new Query ( ' companies ' , ' TechCo ' ))
-> setArguments ([ ' name ' => ' Tech Co. ' ])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
),
( new Query ( ' companies ' , ' AnotherTechCo ' ))
-> setArguments ([ ' name ' => ' A.N. Other Tech Co. ' ])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
)
]
);
Für den Fall, dass dasselbe Objekt mehrmals mit unterschiedlichen Argumenten abgerufen werden muss, kann im zweiten Argument des Abfragekonstruktors ein Alias festgelegt werden.
$ gql = ( new Query ( ' companies ' ))
-> setAlias ( ' CompanyAlias ' )
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
Der Alias kann auch über die Setter-Methode festgelegt werden.
Wenn Sie ein Feld abfragen, das einen Schnittstellentyp zurückgibt, müssen Sie möglicherweise Inline-Fragmente verwenden, um auf Daten zum zugrunde liegenden konkreten Typ zuzugreifen.
Dieses Beispiel zeigt, wie man mit diesem Paket Inline-Fragmente generiert:
$ gql = new Query ( ' companies ' );
$ gql -> setSelectionSet (
[
' serialNumber ' ,
' name ' ,
( new InlineFragment ( ' PrivateCompany ' ))
-> setSelectionSet (
[
' boardMembers ' ,
' shareholders ' ,
]
),
]
);
Mit der QueryBuilder-Klasse können Query-Objekte dynamisch erstellt werden, was in manchen Fällen nützlich sein kann. Sie funktioniert sehr ähnlich wie die Query-Klasse, der Query-Aufbau ist jedoch in Schritte unterteilt.
So kann das Beispiel „Query With Input Object Argument“ mit dem QueryBuilder erstellt werden:
$ builder = ( new QueryBuilder ( ' companies ' ))
-> setVariable ( ' namePrefix ' , ' String ' , true )
-> setArgument ( ' filter ' , new RawObject ( ' {name_starts_with: $namePrefix} ' ))
-> selectField ( ' name ' )
-> selectField ( ' serialNumber ' );
$ gql = $ builder -> getQuery ();
Wie bei der Query-Klasse kann mithilfe des zweiten Konstruktorarguments ein Alias festgelegt werden.
$ builder = ( new QueryBuilder ( ' companies ' , ' CompanyAlias ' ))
-> selectField ( ' name ' )
-> selectField ( ' serialNumber ' );
$ gql = $ builder -> getQuery ();
Oder über die Setter-Methode
$ builder = ( new QueryBuilder ( ' companies ' ))
-> setAlias ( ' CompanyAlias ' )
-> selectField ( ' name ' )
-> selectField ( ' serialNumber ' );
$ gql = $ builder -> getQuery ();
Genau wie die Query-Klasse kann die QueryBuilder-Klasse in vollständiger Form geschrieben werden, um das Schreiben mehrerer Abfragen unter einem Abfrage-Builder-Objekt zu ermöglichen. Nachfolgend finden Sie ein Beispiel dafür, wie das vollständige Formular mit dem QueryBuilder verwendet werden kann:
$ builder = ( new QueryBuilder ())
-> setVariable ( ' namePrefix ' , ' String ' , true )
-> selectField (
( new QueryBuilder ( ' companies ' ))
-> setArgument ( ' filter ' , new RawObject ( ' {name_starts_with: $namePrefix} ' ))
-> selectField ( ' name ' )
-> selectField ( ' serialNumber ' )
)
-> selectField (
( new QueryBuilder ( ' company ' ))
-> setArgument ( ' serialNumber ' , 123 )
-> selectField ( ' name ' )
);
$ gql = $ builder -> getQuery ();
Diese Abfrage ist eine Erweiterung der Abfrage im vorherigen Beispiel. Es werden alle Unternehmen zurückgegeben, die mit einem Namenspräfix beginnen, und das Unternehmen mit der serialNumber
mit dem Wert 123, beide in derselben Antwort.
Ein Client-Objekt kann einfach durch Bereitstellung der GraphQL-Endpunkt-URL instanziiert werden.
Der Client-Konstruktor erhält außerdem ein optionales „authorizationHeaders“-Array, mit dem allen an den GraphQL-Server gesendeten Anforderungen Autorisierungsheader hinzugefügt werden können.
Beispiel:
$ client = new Client (
' http://api.graphql.com ' ,
[ ' Authorization ' => ' Basic xyz ' ]
);
Der Client-Konstruktor erhält außerdem ein optionales „httpOptions“-Array, das die „authorizationHeaders“ überschreibt und zum Hinzufügen benutzerdefinierter Guzzle-HTTP-Client-Anforderungsoptionen verwendet werden kann.
Beispiel:
$ client = new Client (
' http://api.graphql.com ' ,
[],
[
' connect_timeout ' => 5 ,
' timeout ' => 5 ,
' headers ' => [
' Authorization ' => ' Basic xyz '
'User-Agent' => ' testing/1.0 ' ,
],
' proxy ' => [
' http ' => ' tcp://localhost:8125 ' , // Use this proxy with "http"
' https ' => ' tcp://localhost:9124 ' , // Use this proxy with "https",
' no ' => [ ' .mit.edu ' , ' foo.com ' ] // Don't use a proxy with these
],
' cert ' => [ ' /path/server.pem ' , ' password ' ]
. . .
]
);
Es ist möglich, einen eigenen vorkonfigurierten HTTP-Client zu verwenden, der die PSR-18-Schnittstelle implementiert.
Beispiel:
$ client = new Client (
' http://api.graphql.com ' ,
[],
[],
$ myHttpClient
);
Abfrage mit dem GraphQL-Client ausführen und die Ergebnisse in der Objektstruktur abrufen:
$ results = $ client -> runQuery ( $ gql );
$ results -> getData ()-> companies [ 0 ]-> branches ;
Oder Ergebnisse in Array-Struktur erhalten:
$ results = $ client -> runQuery ( $ gql , true );
$ results -> getData ()[ ' companies ' ][ 1 ][ ' branches ' ][ ' address ' ];
Das Ausführen von Abfragen, die Variablen enthalten, erfordert die Übergabe eines assoziativen Arrays, das Variablennamen (Schlüssel) Variablenwerten (Werten) an die runQuery
Methode zuordnet. Hier ist ein Beispiel:
$ gql = ( new Query ( ' companies ' ))
-> setVariables (
[
new Variable ( ' name ' , ' String ' , true ),
new Variable ( ' limit ' , ' Int ' , false , 5 )
]
)
-> setArguments ([ ' name ' => ' $name ' , ' first ' => ' $limit ' ])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
$ variablesArray = [ ' name ' => ' Tech Co. ' , ' first ' => 5 ];
$ results = $ client -> runQuery ( $ gql , true , $ variablesArray );
Mutationen folgen den gleichen Regeln wie Abfragen in GraphQL: Sie wählen Felder für zurückgegebene Objekte aus, empfangen Argumente und können Unterfelder haben.
Hier ist ein Beispielbeispiel für die Erstellung und Ausführung von Mutationen:
$ mutation = ( new Mutation ( ' createCompany ' ))
-> setArguments ([ ' companyObject ' => new RawObject ( ' {name: "Trial Company", employees: 200} ' )])
-> setSelectionSet (
[
' _id ' ,
' name ' ,
' serialNumber ' ,
]
);
$ results = $ client -> runQuery ( $ mutation );
Mutationen können vom Client auf die gleiche Weise ausgeführt werden wie Abfragen.
Mutationen können die Variablen auf die gleiche Weise nutzen wie Abfragen. Hier ist ein Beispiel für die Verwendung der Variablen zur dynamischen Übergabe von Eingabeobjekten an den GraphQL-Server:
$ mutation = ( new Mutation ( ' createCompany ' ))
-> setVariables ([ new Variable ( ' company ' , ' CompanyInputObject ' , true )])
-> setArguments ([ ' companyObject ' => ' $company ' ]);
$ variables = [ ' company ' => [ ' name ' => ' Tech Company ' , ' type ' => ' Testing ' , ' size ' => ' Medium ' ]];
$ client -> runQuery (
$ mutation , true , $ variables
);
Dies sind die resultierende Mutation und die damit übergebenen Variablen:
mutation( $ company : CompanyInputObject!) {
createCompany (companyObject: $ company )
}
{"company":{"name":"Tech Company", " type " :"Testing", " size " :"Medium"}}
GraphQL Pokemon ist eine sehr coole öffentliche GraphQL-API zum Abrufen von Pokemon-Daten. Die API ist öffentlich im Web verfügbar. Wir werden sie verwenden, um die Funktionen dieses Clients zu demonstrieren.
Github Repo-Link: https://github.com/lucasbento/graphql-pokemon
API-Link: https://graphql-pokemon.now.sh/
Diese Abfrage ruft die Entwicklungen aller Pokémon und ihre Angriffe ab:
query( $ name : String!) {
pokemon (name: $ name ) {
id
number
name
evolutions {
id
number
name
weight {
minimum
maximum
}
attacks {
fast {
name
type
damage
}
}
}
}
}
So kann diese Abfrage mit der Abfrageklasse geschrieben und mit dem Client ausgeführt werden:
$ client = new Client (
' https://graphql-pokemon.now.sh/ '
);
$ gql = ( new Query ( ' pokemon ' ))
-> setVariables ([ new Variable ( ' name ' , ' String ' , true )])
-> setArguments ([ ' name ' => ' $name ' ])
-> setSelectionSet (
[
' id ' ,
' number ' ,
' name ' ,
( new Query ( ' evolutions ' ))
-> setSelectionSet (
[
' id ' ,
' number ' ,
' name ' ,
( new Query ( ' attacks ' ))
-> setSelectionSet (
[
( new Query ( ' fast ' ))
-> setSelectionSet (
[
' name ' ,
' type ' ,
' damage ' ,
]
)
]
)
]
)
]
);
try {
$ name = readline ( ' Enter pokemon name: ' );
$ results = $ client -> runQuery ( $ gql , true , [ ' name ' => $ name ]);
}
catch ( QueryError $ exception ) {
print_r ( $ exception -> getErrorDetails ());
exit ;
}
print_r ( $ results -> getData ()[ ' pokemon ' ]);
Oder alternativ: So kann diese Abfrage mit der QueryBuilder-Klasse generiert werden:
$ client = new Client (
' https://graphql-pokemon.now.sh/ '
);
$ builder = ( new QueryBuilder ( ' pokemon ' ))
-> setVariable ( ' name ' , ' String ' , true )
-> setArgument ( ' name ' , ' $name ' )
-> selectField ( ' id ' )
-> selectField ( ' number ' )
-> selectField ( ' name ' )
-> selectField (
( new QueryBuilder ( ' evolutions ' ))
-> selectField ( ' id ' )
-> selectField ( ' name ' )
-> selectField ( ' number ' )
-> selectField (
( new QueryBuilder ( ' attacks ' ))
-> selectField (
( new QueryBuilder ( ' fast ' ))
-> selectField ( ' name ' )
-> selectField ( ' type ' )
-> selectField ( ' damage ' )
)
)
);
try {
$ name = readline ( ' Enter pokemon name: ' );
$ results = $ client -> runQuery ( $ builder , true , [ ' name ' => $ name ]);
}
catch ( QueryError $ exception ) {
print_r ( $ exception -> getErrorDetails ());
exit ;
}
print_r ( $ results -> getData ()[ ' pokemon ' ]);
Obwohl dies nicht das Hauptziel dieses Pakets ist, unterstützt es das Ausführen von Rohzeichenfolgenabfragen, genau wie jeder andere Client, der die runRawQuery
-Methode in der Client
-Klasse verwendet. Hier ist ein Beispiel für die Verwendung:
$ gql = <<<QUERY
query {
pokemon(name: "Pikachu") {
id
number
name
attacks {
special {
name
type
damage
}
}
}
}
QUERY ;
$ results = $ client -> runRawQuery ( $ gql );