一款以 PHP 編寫的 GraphQL 用戶端,提供非常簡單但功能強大的查詢產生器類,讓與 GraphQL 伺服器互動的過程變得非常簡單。
使用此套件產生 GraphQL 查詢有 3 種主要方法:
Query物件的建構器類別。它的設計用於以動態方式建立查詢的情況。執行以下命令以使用 Composer 安裝軟體包:
$ composer require gmostafa/php-graphql-client
為了避免編寫任何查詢並僅與 API 模式產生的 PHP 物件互動的麻煩,請造訪 PHP GraphQL OQM 儲存庫
$ gql = ( new Query ( ' companies ' ))
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);這個簡單的查詢將檢索顯示其名稱和序號的所有公司。
上一個範例中提供的查詢以「速記形式」表示。速記形式涉及編寫更少數量的程式碼行,從而加快編寫查詢的過程。以下是與上一個範例中編寫的完全相同的查詢的完整形式的範例。
$ gql = ( new Query ())
-> setSelectionSet (
[
( new Query ( ' companies ' ))
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
)
]
);從範例中可以看出,速記形式更易於閱讀和書寫,與完整形式相比,通常更喜歡使用速記形式。
除非查詢無法以簡寫形式表示,否則不應使用完整形式,當我們想要在同一物件中執行多個查詢時,簡寫形式只有一種情況。
$ gql = ( new Query ())
-> setSelectionSet (
[
( new Query ( ' companies ' ))
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
),
( new Query ( ' countries ' ))
-> setSelectionSet (
[
' name ' ,
' code ' ,
]
)
]
);此查詢檢索顯示每個公司和國家/地區的一些資料欄位的所有公司和國家/地區。它基本上在一個查詢物件信封中運行兩個(或更多,如果需要)獨立的查詢。
編寫多個查詢需要以完整形式編寫查詢對象,以將每個查詢表示為父查詢對像下的子欄位。
$ gql = ( new Query ( ' companies ' ))
-> setSelectionSet (
[
' name ' ,
' serialNumber ' ,
( new Query ( ' branches ' ))
-> setSelectionSet (
[
' address ' ,
( new Query ( ' contracts ' ))
-> setSelectionSet ([ ' date ' ])
]
)
]
);該查詢是一個更複雜的查詢,不僅檢索標量字段,還檢索物件字段。此查詢返回所有公司,顯示其名稱、序號,對於每個公司,其所有分支機構,顯示分支機構地址,對於每個地址,它檢索綁定到該地址的所有合同,顯示其日期。
$ gql = ( new Query ( ' companies ' ))
-> setArguments ([ ' name ' => ' Tech Co. ' , ' first ' => 3 ])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);此查詢不會透過新增參數來檢索所有公司。此查詢將檢索名稱為「Tech Co.」的前 3 家公司,並顯示它們的名稱和序號。
$ gql = ( new Query ( ' companies ' ))
-> setArguments ([ ' serialNumbers ' => [ 159 , 260 , 371 ]])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);此查詢是參數查詢的特例。在此範例中,查詢將僅檢索序號為 159、260 和 371 之一的公司,並顯示名稱和序號。
$ gql = ( new Query ( ' companies ' ))
-> setArguments ([ ' filter ' => new RawObject ( ' {name_starts_with: "Face"} ' )])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);此查詢是參數查詢的另一個特殊情況。在此範例中,我們設定一個自訂輸入物件“過濾器”,其中包含一些值來限制返回的公司。我們將過濾器“name_starts_with”設定為“Face”值。此查詢將僅檢索名稱以短語“Face”開頭的公司。
正在建構的 RawObject 類別用於將字串原樣注入到查詢中。無論輸入到 RawObject 建構函數中的字串是什麼,都會原樣放入查詢中,而不需要查詢類別通常完成的任何自訂格式。
$ gql = ( new Query ( ' companies ' ))
-> setVariables (
[
new Variable ( ' name ' , ' String ' , true ),
new Variable ( ' limit ' , ' Int ' , false , 5 )
]
)
-> setArguments ([ ' name ' => ' $name ' , ' first ' => ' $limit ' ])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);此查詢顯示如何在此套件中使用變數以允許 GraphQL 標準啟用的動態請求。
Variable 類別是一個不可變類,表示 GraphQL 標準中的變數。它的建構子接收 4 個參數:
$ 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 '
]
)
]
);當需要使用不同參數多次檢索相同物件時,可以在 Query 建構函數的第二個參數中設定別名。
$ gql = ( new Query ( ' companies ' ))
-> setAlias ( ' CompanyAlias ' )
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);別名也可以透過 setter 方法設定。
當查詢傳回介面類型的欄位時,您可能需要使用內聯片段來存取底層特定類型的資料。
此範例展示如何使用此套件產生內聯片段:
$ gql = new Query ( ' companies ' );
$ gql -> setSelectionSet (
[
' serialNumber ' ,
' name ' ,
( new InlineFragment ( ' PrivateCompany ' ))
-> setSelectionSet (
[
' boardMembers ' ,
' shareholders ' ,
]
),
]
);QueryBuilder 類別可用於動態建構 Query 對象,這在某些情況下很有用。它的運作方式與 Query 類別非常相似,但 Query 建置分為多個步驟。
這就是如何使用 QueryBuilder 建立「使用輸入物件參數的查詢」範例:
$ builder = ( new QueryBuilder ( ' companies ' ))
-> setVariable ( ' namePrefix ' , ' String ' , true )
-> setArgument ( ' filter ' , new RawObject ( ' {name_starts_with: $namePrefix} ' ))
-> selectField ( ' name ' )
-> selectField ( ' serialNumber ' );
$ gql = $ builder -> getQuery ();與 Query 類別一樣,可以使用第二個建構函數參數來設定別名。
$ builder = ( new QueryBuilder ( ' companies ' , ' CompanyAlias ' ))
-> selectField ( ' name ' )
-> selectField ( ' serialNumber ' );
$ gql = $ builder -> getQuery ();或透過setter方法
$ builder = ( new QueryBuilder ( ' companies ' ))
-> setAlias ( ' CompanyAlias ' )
-> selectField ( ' name ' )
-> selectField ( ' serialNumber ' );
$ gql = $ builder -> getQuery ();就像 Query 類別一樣,QueryBuilder 類別可以以完整形式編寫,以便能夠在一個查詢生成器物件下編寫多個查詢。以下是完整表單如何與 QueryBuilder 一起使用的範例:
$ 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 ();此查詢是上一範例中查詢的擴充。它會傳回以名稱前綴開頭的所有公司,並傳回serialNumber值為 123 的公司,兩者都在同一回應中。
透過提供 GraphQL 端點 URL 可以輕鬆實例化 Client 物件。
Client 建構函式也會接收一個可選的「authorizationHeaders」數組,該數組可用於向發送到 GraphQL 伺服器的所有請求新增授權標頭。
例子:
$ client = new Client (
' http://api.graphql.com ' ,
[ ' Authorization ' => ' Basic xyz ' ]
);用戶端建構函式也會接收一個可選的「httpOptions」數組,該數組會覆蓋「authorizationHeaders」並可用於新增自訂 Guzzle HTTP 用戶端請求選項。
例子:
$ 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 ' ]
. . .
]
);可以使用您自己的預先配置 HTTP 用戶端來實作 PSR-18 介面。
例子:
$ client = new Client (
' http://api.graphql.com ' ,
[],
[],
$ myHttpClient
);使用 GraphQL 用戶端執行查詢並以物件結構取得結果:
$ results = $ client -> runQuery ( $ gql );
$ results -> getData ()-> companies [ 0 ]-> branches ;或以數組結構取得結果:
$ results = $ client -> runQuery ( $ gql , true );
$ results -> getData ()[ ' companies ' ][ 1 ][ ' branches ' ][ ' address ' ];執行包含變數的查詢需要將一個關聯數組傳遞給runQuery方法,該數組將變數名稱(鍵)對應到變數值(值)。這是一個例子:
$ 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 );突變遵循 GraphQL 中查詢的相同規則,它們選擇傳回物件上的欄位、接收參數並且可以具有子欄位。
以下是有關如何建構和運行突變的範例:
$ mutation = ( new Mutation ( ' createCompany ' ))
-> setArguments ([ ' companyObject ' => new RawObject ( ' {name: "Trial Company", employees: 200} ' )])
-> setSelectionSet (
[
' _id ' ,
' name ' ,
' serialNumber ' ,
]
);
$ results = $ client -> runQuery ( $ mutation );客戶端可以以與執行查詢相同的方式運行突變。
突變可以像查詢一樣利用變數。以下是如何使用變數將輸入物件動態傳遞到 GraphQL 伺服器的範例:
$ 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
);這些是產生的突變以及隨之傳遞的變數:
mutation( $ company : CompanyInputObject!) {
createCompany (companyObject: $ company )
}
{"company":{"name":"Tech Company", " type " :"Testing", " size " :"Medium"}}GraphQL Pokemon 是一個非常酷的公共 GraphQL API,可用於檢索 Pokemon 資料。該 API 可在網路上公開獲取,我們將使用它來演示該客戶端的功能。
Github 儲存庫連結:https://github.com/lucasbento/graphql-pokemon
API連結:https://graphql-pokemon.now.sh/
此查詢檢索任何口袋妖怪的進化及其攻擊:
query( $ name : String!) {
pokemon (name: $ name ) {
id
number
name
evolutions {
id
number
name
weight {
minimum
maximum
}
attacks {
fast {
name
type
damage
}
}
}
}
}這就是如何使用查詢類別編寫此查詢並使用客戶端運行的方式:
$ 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 ' ]);或者,這就是使用 QueryBuilder 類別產生此查詢的方式:
$ 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 ' ]);雖然不是這個套件的主要目標,但它支援運行原始字串查詢,就像使用Client類別中的runRawQuery方法的任何其他客戶端一樣。以下是有關如何使用它的範例:
$ gql = <<<QUERY
query {
pokemon(name: "Pikachu") {
id
number
name
attacks {
special {
name
type
damage
}
}
}
}
QUERY ;
$ results = $ client -> runRawQuery ( $ gql );