您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)PHP中怎么安裝和使用GraphQL,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
php,一個(gè)嵌套的縮寫(xiě)名稱,是英文超級(jí)文本預(yù)處理語(yǔ)言(PHP:Hypertext Preprocessor)的縮寫(xiě)。PHP 是一種 HTML 內(nèi)嵌式的語(yǔ)言,PHP與微軟的ASP頗有幾分相似,都是一種在服務(wù)器端執(zhí)行的嵌入HTML文檔的腳本語(yǔ)言,語(yǔ)言的風(fēng)格有類似于C語(yǔ)言,現(xiàn)在被很多的網(wǎng)站編程人員廣泛的運(yùn)用。
GraphQL 是一種現(xiàn)代化的 HTTP API 接口構(gòu)建方式,客戶端可以按需
查詢需要的數(shù)據(jù)。
GraphQL 可以提升 API 調(diào)用的靈活性,我們可以像寫(xiě)數(shù)據(jù)庫(kù)查詢語(yǔ)句一樣來(lái)請(qǐng)求 API 來(lái)獲取所需要的數(shù)據(jù),這對(duì)構(gòu)建復(fù)雜的 API 查詢來(lái)說(shuō)非常有用。
REST的核心思想就是資源,每個(gè)資源都能用一個(gè)URL來(lái)表示,你能通過(guò)一個(gè)GET請(qǐng)求訪問(wèn)該URL從而獲取該資源。根據(jù)當(dāng)今大多數(shù)API的定義,你很有可能會(huì)得到一份JSON格式的數(shù)據(jù)響應(yīng),整個(gè)過(guò)程大概是這樣:
GET /user/1 { "username":"姓名", "age":20, "sex":"男" }
GET /book/1 { "book":"書(shū)名", "author":"作者", "country":"中國(guó)" }
從上面的示例可以看出,如果前端需要user/1
和book/1
的時(shí)候需要調(diào)用2次
接口,并且如果前端只需要user/1
里面的username
,而上面的接口獲取了username
以外的數(shù)據(jù),那么對(duì)于前端而言,除 username
之外的數(shù)據(jù)無(wú)處可用,造成了資源的浪費(fèi)。
如果我們使用GraphQL
來(lái)進(jìn)行查詢的話,與REST方式相比,只需要調(diào)用一次并且可以查詢我們指定的字段,避免了資源的浪費(fèi),并且更加高效。
query { user(id:1) { username } book(id:1){ book, author, country } }
推薦學(xué)習(xí):《PHP視頻教程》
composer require webonyx/graphql-php
1、安裝完成之后,我們先編寫(xiě)一個(gè)簡(jiǎn)單示例,來(lái)看看graphql-php怎么用,具體代碼如下:這段代碼中,我們定義了一個(gè)名為phoneNumber
的字段,然后通過(guò)postman來(lái)調(diào)用我們編寫(xiě)的代碼。
<?php require_once __DIR__ . '/vendor/autoload.php'; use GraphQL\Type\Schema; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; use GraphQL\GraphQL; $queryType = new ObjectType([ 'name' => 'Query', 'fields' => [ 'phoneNumber' => [ 'type' => Type::int(), 'resolve' => function () { return 1875555555; } ] ], ]); $schema = new Schema([ 'query' => $queryType, ]); $rawInput = file_get_contents('php://input'); $input = json_decode($rawInput, true); $query = $input['query']; $variableValues = isset($input['variables']) ? $input['variables'] : null; try { $rootValue = ['prefix' => 'prefix: ']; $result = GraphQL::executeQuery($schema, $query, $rootValue, null, $variableValues); $output = $result->toArray(); } catch (\Exception $e) { $output = [ 'errors' => [ [ 'message' => $e->getMessage() ] ] ]; } header('Content-Type: application/json'); echo json_encode($output);
2、使用postman來(lái)調(diào)用我們剛剛編寫(xiě)的代碼,以下是我們查詢結(jié)果的示例
從上面的示例中,我們可以看到示例主要引入了4個(gè)類
use GraphQL\Type\Schema; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; use GraphQL\GraphQL;
Schema 是類型層次結(jié)構(gòu)的容器,它接受構(gòu)造函數(shù)中的根類型并向內(nèi)部 GrahpQL 工具提供接收你的類型信息的方法。
包含以下選項(xiàng)的數(shù)組:
Option | Type | Notes |
---|---|---|
query | ObjectType | 必須。 讀取 API 中包含根級(jí)字段的對(duì)象類型 (通常命名為 "Query"),用于讀取數(shù)據(jù) |
mutation | ObjectType | 寫(xiě)入 API 中包含根級(jí)字段的對(duì)象類型 (通常命名為 "Mutation"),數(shù)據(jù)變更時(shí)會(huì)用到 |
subscription | ObjectType | 保留用于將來(lái)的描述實(shí)現(xiàn)。目前表現(xiàn)為 graphql-js 自檢查詢的兼容,用于各種客戶端 (如 Relay 或 GraphiQL) |
directives | Directive[] | 默認(rèn)包含內(nèi)建指令 @skip 和 @include 。 如果你傳遞自定義指令并且依然想使用內(nèi)建指令,請(qǐng)聲明添加它們。例如: array_merge(GraphQL::getStandardDirectives(), [$myCustomDirective]); |
types | ObjectType[] | 對(duì)象類型類表,它在靜態(tài) schema 解析期間是不能被 graphql-php 發(fā)現(xiàn)的。 大多數(shù)情況下,對(duì)象類型未曾在字段中被直接引用,但它依然是 schema 的一部分時(shí)會(huì)用到,因?yàn)樗鼘?shí)現(xiàn)了一個(gè)在 resolveType 中調(diào)用解析為此對(duì)象類型的接口。 請(qǐng)注意,您在此處無(wú)需傳遞所有類型 ,它只是具體用例的解決方法。 |
typeLoader | callable | function($name) 返回給定的類型實(shí)例名稱。 多次調(diào)用情況下,必須返回同樣的實(shí)例。 查閱下文延遲類型加載部分。 |
GraphQL\Type\Definition\ObjectType
對(duì)象類型是典型的 GraphQL 應(yīng)用程序中使用最頻繁的基元。
Option | Type | Notes |
---|---|---|
name | string | 必須。 Schema 中此對(duì)象的唯一名稱 |
fields | array or callable | 必須。 描述對(duì)象字段或可調(diào)用返回此類數(shù)組的數(shù)組。 |
description | string | 呈現(xiàn)于客戶端的參數(shù)文本說(shuō)明(例如:用于 GraphiQL 自動(dòng)生成文檔 ) |
interfaces | array or callable | 此類型實(shí)現(xiàn)的接口列表或返回此類列表的可調(diào)用接口。 |
<?php use GraphQL\Type\Definition\Type; // 內(nèi)置標(biāo)量類型 Type::string(); // String 類型 Type::int(); // Int 類型 Type::float(); // Float 類型 Type::boolean(); // Boolean 類型 Type::id(); // ID 類型
GraphQL 對(duì)象類型上的所有字段都有 0 個(gè)或多個(gè)參數(shù),使用在 args 的字段定義上。每個(gè)參數(shù)數(shù)組參考以下說(shuō)明:
Option | Type | Notes |
---|---|---|
name | string | 必須。 參數(shù)名稱。 為空時(shí),使用 args 數(shù)組鍵值 |
type | Type | 必須。 |
description | string | 呈現(xiàn)于客戶端的參數(shù)文本說(shuō)明 |
defaultValue | scalar | 當(dāng)前參數(shù)默認(rèn)值 |
示例
$queryType = new ObjectType([ 'name' => 'Query', 'fields' => [ 'phoneNumber' => [ 'type' => Type::int(), 'resolve' => function () { return 1875555555; } ] ], ]);
GraphQL類主要在查詢的時(shí)候用到,我們可以用 GraphQL::executeQuery 方法來(lái)執(zhí)行查詢
executeQuery 方法的參數(shù)說(shuō)明
參數(shù) | 類型 | 說(shuō)明 |
---|---|---|
schema | GraphQL\Type\Schema | 必須。 Schema應(yīng)用實(shí)例 |
queryString | string or GraphQL\Language\AST\DocumentNode | 必須。 解析,驗(yàn)證并執(zhí)行現(xiàn)有的 GraphQL 查詢字符。 如果在執(zhí)行之前解析其他查詢,則在此處傳遞相應(yīng)的 AST 文檔節(jié)點(diǎn)來(lái)避免新的解析。 |
rootValue | mixed | 表示數(shù)據(jù)圖結(jié)構(gòu)的基礎(chǔ)值。作為Query type 字段解析傳遞的第一個(gè)參數(shù)。如果現(xiàn)有該值已被 Query type 解析過(guò),則可忽略或設(shè)置為 null 值。 |
context | mixed | 字段解析器的共享信息。 常用來(lái)傳遞已登錄用戶信息,位置詳情等。 它將用在所有字段解析器的第 3 個(gè)參數(shù)。 |
variableValues | array | 變量的映射,該值將隨同查詢字符串一起傳遞。請(qǐng)查閱 GraphQL官網(wǎng)查詢變量的相關(guān)。 |
operationName | string | 指定請(qǐng)求方可執(zhí)行的操作, 防止條件查詢字符包含多級(jí)操作。 |
fieldResolver | callable | Schema 參數(shù) schema 中未實(shí)現(xiàn)的解析器函數(shù)。 |
validationRules | array | 查詢驗(yàn)證規(guī)則組,默認(rèn)所有規(guī)則??諗?shù)組將跳過(guò)查詢驗(yàn)證 (對(duì)于持久化查詢將會(huì)比較方便,查詢會(huì)在持久化之前默認(rèn)已驗(yàn)證,并在執(zhí)行期間假設(shè)符合規(guī)則)。 |
use GraphQL\GraphQL; $result = GraphQL::executeQuery( $schema, $queryString, $rootValue = null, $context = null, $variableValues = null, $operationName = null, $fieldResolver = null, $validationRules = null );
我們介紹完GraphQL幾個(gè)概念之后,用幾個(gè)簡(jiǎn)單的示例帶大家來(lái)體驗(yàn)一下。
在這個(gè)示例中我們定義了2個(gè)字段,分別是phoneNumber
和echo
,其中phoneNumber為 Type::int()
類型,echo
為Type::string()
類型,同時(shí)echo
字段帶有一個(gè)參數(shù)為message
<?php require_once __DIR__ . '/vendor/autoload.php'; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; use GraphQL\GraphQL; use GraphQL\Type\Schema; $queryType = new ObjectType([ 'name' => 'Query', 'fields' => [ 'phoneNumber' => [ 'type' => Type::int(), 'resolve' => function () { return 1875555555; } ], 'echo' => [ 'type' => Type::string(), 'args' => [ 'message' => Type::string(), ], 'resolve' => function ($root, $args) { return 'echo msg result:' . ($args['message'] ?? 'nothing'); } ], ], ]); $schema = new Schema([ 'query' => $queryType ]); $rawInput = file_get_contents('php://input'); $input = json_decode($rawInput, true); $query = $input['query']; $variableValues = isset($input['variables']) ? $input['variables'] : null; try { $rootValue = ['prefix' => 'prefix: ']; $result = GraphQL::executeQuery($schema, $query, $rootValue, null, $variableValues); $output = $result->toArray(); } catch (\Exception $e) { $output = [ 'errors' => [ [ 'message' => $e->getMessage() ] ] ]; } header('Content-Type: application/json'); echo json_encode($output);
我們可以看到,在請(qǐng)求時(shí)我們傳了phoneNumber
和echo
兩個(gè)字段,并且message
為test
。
我們?cè)谏厦嬲f(shuō)過(guò),對(duì)象類型是典型的 GraphQL 應(yīng)用程序中使用最頻繁的基元,一個(gè)對(duì)象類型里面可以包含寧外一個(gè)對(duì)象類型,我們可以新定義一個(gè)名為$userType
的ObjectType
,然后在oneUser
指定它的類型為$userType
,這樣我們執(zhí)行查詢的時(shí)候,oneUser
就會(huì)返回一個(gè)對(duì)象。
<?php require_once __DIR__ . '/vendor/autoload.php'; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; use GraphQL\GraphQL; use GraphQL\Type\Schema; $userType = new ObjectType([ 'name' => 'userType', 'description' => '用戶詳情', 'fields' => [ 'uid' => [ 'type' => Type::int(), 'description' => '用戶ID' ], 'name' => Type::string() ] ]); $queryType = new ObjectType([ 'name' => 'Query', 'fields' => [ 'oneUser' => [ 'type' => $userType, // 我們這里指定type為我們上面創(chuàng)建的$userType 'description' => '用戶列表', 'args' => [ 'uid' => [ 'type' => Type::int(), 'defaultValue' => 222 ] ], 'resolve' => function($root, $args) { return [ "uid" => $args['user_id'] ?? 3, "name" => "xzl", ]; } ], ] ]); $schema = new Schema([ 'query' => $queryType ]); $rawInput = file_get_contents('php://input'); $input = json_decode($rawInput, true); $query = $input['query']; $variableValues = isset($input['variables']) ? $input['variables'] : null; try { $rootValue = ['prefix' => 'prefix: ']; $result = GraphQL::executeQuery($schema, $query, $rootValue, null, $variableValues); $output = $result->toArray(); } catch (\Exception $e) { $output = [ 'errors' => [ [ 'message' => $e->getMessage() ] ] ]; } header('Content-Type: application/json'); echo json_encode($output);
在平時(shí)的開(kāi)發(fā)請(qǐng)求中,我們從后端接口獲取數(shù)據(jù)的時(shí)候,大部分都是以列表的形式返回的,我們可以通過(guò)Type::listOf
方法來(lái)指定我們返回的字段是一個(gè)列表。
<?php require_once __DIR__ . '/vendor/autoload.php'; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; use GraphQL\GraphQL; use GraphQL\Type\Schema; class User { // 模擬從數(shù)據(jù)庫(kù)取數(shù)據(jù) public static function getUserLimit($limit) { $user = [ [ "uid" => 1, "name" => "name1" ], [ "uid" => 2, "name" => "name2" ], [ "uid" => 3, "name" => "name3" ], [ "uid" => 4, "name" => "name4" ] ]; return array_slice($user, 0, $limit); } } $userType = new ObjectType([ 'name' => 'userType', 'description' => '用戶詳情', 'fields' => [ 'uid' => [ 'type' => Type::int(), 'description' => '用戶ID' ], 'name' => Type::string() ] ]); $queryType = new ObjectType([ 'name' => 'Query', 'fields' => [ 'users' => [ 'type' => Type::listOf($userType), 'description' => '用戶列表', 'args' => [ 'limit' => [ 'type' => Type::int(), 'description' => '限制條數(shù)', 'defaultValue' => 10 ] ], 'resolve' => function($root, $args) { return User::getUserLimit($args['limit']); } ] ] ]); $schema = new Schema([ 'query' => $queryType ]); $rawInput = file_get_contents('php://input'); $input = json_decode($rawInput, true); $query = $input['query']; $variableValues = isset($input['variables']) ? $input['variables'] : null; try { $rootValue = ['prefix' => 'prefix: ']; $result = GraphQL::executeQuery($schema, $query, $rootValue, null, $variableValues); $output = $result->toArray(); } catch (\Exception $e) { $output = [ 'errors' => [ [ 'message' => $e->getMessage() ] ] ]; } header('Content-Type: application/json'); echo json_encode($output);
從上面結(jié)果可以看到,我們傳了limit
參數(shù)為2,最終從我們模擬的數(shù)據(jù)里面取出了2條數(shù)據(jù)
在上面的示例中,如果我們代碼返回的數(shù)據(jù)比較復(fù)雜時(shí),需要編寫(xiě)大量的代碼,通過(guò)GraphQL類型語(yǔ)言,我們可以減少代碼量,使代碼看上去更加簡(jiǎn)潔,這是一個(gè)用 GraphQL 類型語(yǔ)言定義的簡(jiǎn)單 Schema示例。
<?php require_once __DIR__ . '/vendor/autoload.php'; use GraphQL\GraphQL; use GraphQL\Utils\BuildSchema; // graph.graphql 文件內(nèi)容 $graph = <<<GRAPH schema { query: Query } type Query { graph_test: String echo(message: String): String show_test: Show show_test_arr: [Show] } type Show { content: String! text: String! } GRAPH; $schema = BuildSchema::build($graph); $rawInput = file_get_contents('php://input'); $input = json_decode($rawInput, true); $query = $input['query']; $variableValues = isset($input['variables']) ? $input['variables'] : null; try { $rootValue = [ 'sum' => function($rootValue, $args, $context) { return $args['x'] + $args['y']; }, 'echo' => function($rootValue, $args, $context) { return $rootValue['prefix'] . ($args['message'] ?? 'no echo'); }, 'show_test' => function($rootValue, $args, $context) { return [ 'content' => 'show_content', 'text' => 'xxxx xxx' ]; }, 'show_test_arr' => function($rootValue, $args, $context) { return [ [ 'content' => 'show_content', 'text' => 'xxxx xxx' ], [ 'content' => 'show_content_2', 'text' => 'xxxx xxx_2' ] ]; }, 'prefix' => 'from test:', "graph_test" => "graphql_test" ];; $result = GraphQL::executeQuery($schema, $query, $rootValue, null, $variableValues); $output = $result->toArray(); } catch (\Exception $e) { \GraphQL\Server\StandardServer::send500Error($e); } header('Content-Type: application/json'); echo json_encode($output);
關(guān)于“PHP中怎么安裝和使用GraphQL”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。