Originally developed at Facebook in 2012 as a better data ingestion solution for underpowered mobile devices, GraphQL was open sourced in 2015. As an API technology designed for flexibility, GraphQL is a powerful enabler for developers and consumers of APIs, as well as the organizations behind them. All details and functionality of the GraphQL implementation are listed in GraphQL Schema
. In order to write a valid GraphQL schema
, you must understand the GraphQL type system.
In this article, you will learn about GraphQL types: five built-in scalar (scalar
) types, enumerations (enums
), lists (list
) and non-null wrapper (non-null
) types, object (object
) types, and the abstract interfaces and union types (union
) that work with them .
Scalar Types
All data in a GraphQL schema is ultimately parsed into various scalar types, representing primitive values. A GraphQL response can be thought of as a tree, with scalar types being the leaves at the end of the tree. There can be multiple levels in a nested response, but the last level will always resolve to a scalar (or enumeration) type. GraphQL comes with five built-in scalar types: Int
, Float
, String
, Boolean
, and ID
.
#Int
Int
is a signed 32
non-decimal value, it is a signed value that does not include decimals (positive or negative) integer. The maximum value of a signed 32
-digit integer is 2,147,483,647
. This is one of two built-in scalars for numeric data.
Float
Float
is a signed double-precision decimal value. It is a signed (positive or negative) number with a decimal point, such as 1.2
, which is another built-in scalar used for numeric data.
String
String
is a sequence of UTF-8
characters. The String
type is used for any text data, this can also include data such as very large numbers. Most custom scalars are string data types.
Boolean
Boolean
contains true
and false
.
ID
ID
is a unique identifier and always serializes as a string, even if ID
is a number . ID
Types can often be represented by universally unique identifiers (UUIDs).
Custom scalar
In addition to the above built-in scalars, you can also use the scalar
keyword to define custom scalars. You can use custom scalars to create types with additional server-level validation, such as Date
, Time
, or Url
. Here's an example of defining a new Date
type:
scalar Date
The server will know how to handle interactions with this new type using GraphQLScalarType.
Enumeration (Enum) type
Enum
type, also called Enumerator
type, is used to describe an Set of possible values.
For example you could create an enumeration for your game character's Job
and Species
that contains all the values ??that the system will accept.
"角色的工作等級" enum Job { FIGHTER WIZARD } "性格的種類或血統(tǒng)" enum Species { HUMAN ELF DWARF }
By defining an enumeration type you can ensure that a role's Job
can only be FIGHTER
or WIZARD
, and will never accidentally become something else Some random strings, if you use the String
type instead of Enum
, they may be other random strings.
Enumerations can also be used as acceptable values ??in parameters. For example, you could make a Hand
enumeration to represent whether the weapon is one-handed (like a short sword) or two-handed (like a heavy axe), and use that to determine whether one or both can be equipped:
enum Hand { SINGLE DOUBLE}"戰(zhàn)士使用的一種武器"type Weapon { name: String! attack: Int range: Int hand: Hand } type Query { weapons(hand: Hand = SINGLE): [Weapon] }
Hand
The enumeration has been declared with SINGLE
and DOUBLE
as values, and the parameters on the weapons
fields have default values SINGLE
, which means if no parameters are passed, it will default back to SINGLE
.
非空類型
可能會注意到內(nèi)置標量列表中缺少 null
或 undefined
(一種被許多語言視為原始類型的常見類型)。 Null
在 GraphQL 中確實存在,表示缺少一個值。默認情況下,GraphQL 中的所有類型都可以為 null
,因此 null
是對任何類型的有效響應(yīng)。為了使值成為必需值,必須將其轉(zhuǎn)換為帶有尾隨感嘆號的 GraphQL 非空類型。 Non-Null
被定義為類型修飾符,這些類型用于修飾它所引用的類型。例如,String
是一個可選的(或可為空的)字符串,而 String!
是必需的(或非空的)字符串。
列表類型
GraphQL 中的 List
類型是另一種類型修飾符。任何用方括號 ([]
) 括起來的類型都會成為 List
類型,這是一個定義列表中每個項目類型的集合,像 JavaScript 中的數(shù)組。
例如,定義為 [Int]
的類型意味著這個集合所有元素的類型為 Int
類型,[String]
將是 String
類型的集合。 Non-Null
和 List
可以一起使用,使一個類型既需要又定義為 List
,例如 [String]!
。
對象類型
如果 GraphQL 標量類型描述分層 GraphQL 響應(yīng)末尾的“葉子”,那么對象類型描述中間的 分支
,并且 GraphQL 模式中的幾乎所有內(nèi)容都是一種對象類型。
對象由命名字段(鍵)列表和每個字段將解析為的值類型組成。對象是用 type
關(guān)鍵字定義的。至少要定義一個或多個字段,字段不能以兩個下劃線(__
)開頭,以免與GraphQL自省系統(tǒng)沖突。
例如創(chuàng)建一個 Fighter
對象來表示游戲中的一種角色:
"具有直接戰(zhàn)斗能力和力量的英雄" type Fighter { id: ID! name: String! level: Int active: Boolean! }
在此示例中,聲明了 Fighter
對象類型,定義了 4 個字段:
id
:非空ID
類型。name
:非空字符串類型。level
:Int
類型。active
:非空布爾類型。
在聲明上方,可以使用雙引號添加注釋,如本例:具有直接戰(zhàn)斗能力和力量的英雄
,這將顯示為類型的描述。
在此示例中,每個字段都解析為標量類型,但對象字段也可以解析為其他對象類型。例如,可以創(chuàng)建一個 Weapon
類型,并且可以設(shè)置 GraphQL 模式,其中 Fighter
上的 weapon
字段將解析為一個 Weapon
對象:
"戰(zhàn)士使用的一種武器" type Weapon { name: String! attack: Int range: Int } "具有直接戰(zhàn)斗能力和力量的英雄" type Fighter { id: ID! name: String! level: Int active: Boolean! weapon: Weapon }
對象也可以嵌套到其他對象的字段中。
根操作類型
有三種特殊對象作為 GraphQL schema
的入口點:Query
、Mutation
和 Subcription
。這些被稱為根操作類型,并遵循與任何其他對象類型相同的規(guī)則。
schema
關(guān)鍵字表示 GraphQL 模式的入口點。根 Query
、Mutation
和 Subcription
類型將位于根模式對象上:
schema { query: Query mutation: Mutation subscription: Subscription }
Query 類型在任何 GraphQL 模式上都是必需的,代表一個讀取請求,類似于 REST API GET
。以下是返回 Fighter
類型列表的根查詢對象的示例:
type Query { fighters: [Fighter] }
Mutations
代表寫入請求,類似于 REST API
中的 POST
、PUT
或 DELETE
。在以下示例中,Mutation
有一個帶有命名參數(shù)(輸入)的 addFighter
字段:
type Mutation { addFighter(input: FighterInput): Fighter }
最后,一個 Subscription
對應(yīng)于一個事件流,它將與 Web 應(yīng)用程序中的 Websocket 結(jié)合使用。如下所示:
type Subscription { randomBattle(enemy: Enemy): BattleResult }
請注意,schema
入口點通常在某些 GraphQL 實現(xiàn)中被抽象掉。
字段參數(shù)
GraphQL 對象的字段本質(zhì)上是返回值的函數(shù),并且它們可以像任何函數(shù)一樣接受參數(shù)。字段參數(shù)由參數(shù)名稱后跟類型定義,參數(shù)可以是任何非對象類型。在此示例中,可以通過 id
字段(解析為非空 ID
類型)過濾 Fighter
對象:
type Query { fighter(id: ID!): Fighter }
這個特定示例對于從數(shù)據(jù)存儲中獲取單個項目很有用,但參數(shù)也可用于過濾、分頁和其他更具體的查詢。
接口類型
與 Object
類型一樣,抽象接口類型由一系列命名字段及其關(guān)聯(lián)的值類型組成。接口看起來像并遵循與對象相同的所有規(guī)則,但用于定義對象實現(xiàn)的子集。
到目前為止,在 schema
中有一個 Fighter
對象,但可能還想創(chuàng)建一個Wizard
、一個 Healer
和其他對象,它們將共享大部分相同的字段但還是存在一些差異。在這種情況下,可以使用接口來定義它們共有的字段,并創(chuàng)建作為接口實現(xiàn)的對象。
在下面的示例中,使用 interface
關(guān)鍵字創(chuàng)建 BaseCharacter
接口,其中包含每種類型的字符將擁有的所有字段:
"A hero on a quest."interface BaseCharacter { id: ID! name: String! level: Int! species: Species job: Job }
每個角色類型都有字段 id
、name
、level
、species
和 job
。
現(xiàn)在,假設(shè)有一個具有這些共享字段的 Fighter
類型和一個 Wizard
類型,但是 Fighters
使用 Weapon
而 Wizards
使用 Spells
??梢允褂?implements
關(guān)鍵字將每個描述為 BaseCharacter
實現(xiàn),這意味著它們必須具有創(chuàng)建的接口中的所有字段:
type Fighter implements BaseCharacter { id: ID! name: String! level: Int! species: Species job: Job! weapon: Weapon } type Wizard implements BaseCharacter { id: ID! name: String! level: Int! species: Species job: Job! spells: [Spell] }
Fighter
和 Wizard
都是 BaseCharacter
接口的有效實現(xiàn),因為它們具有所需的字段子集。
Union 類型
可以與對象一起使用的另一種抽象類型是 union
類型。使用 union
關(guān)鍵字,可以定義一個類型,其中包含所有有效響應(yīng)的對象列表。
使用上面創(chuàng)建的接口,可以創(chuàng)建一個 Character union,將 character
定義為 Wizard
或 Fighter
:
union Character = Wizard | Fighter
等號 =
設(shè)置定義,管道符 |
用作 OR
語句。請注意,union
必須由對象或接口組成,標量類型在 union
上無效。
現(xiàn)在,如果查詢 characters
列表,它可以使用 Character
union
并返回所有 Wizard
和 Fighter
類型。
總結(jié)
上面學(xué)習(xí)了定義 GraphQL 類型系統(tǒng)的類型,包括最基本的類型是標量類型由 Int
、Float
、String
、Boolean
、ID
和 GraphQL 實現(xiàn)創(chuàng)建的任何自定義標量類型組成。枚舉是有效常量值的列表,當需要對查詢響應(yīng)進行更多控制時,可以使用枚舉,而不是簡單地將其聲明為字符串。列表類型和非空類型被稱為類型修飾符 type modifier
或包裝類型 wrapping type
,它們分別可以將其他類型定義為集合類型或必需類型。GraphQL schema
中的幾乎所有內(nèi)容都是對象類型,包括 query
、mutation
和 subscription
入口點。接口和聯(lián)合類型是抽象類型,在定義對象時很有用。
The above is the detailed content of An in-depth analysis of the GraphQL type system. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Go's switch statement will not be executed throughout the process by default and will automatically exit after matching the first condition. 1. Switch starts with a keyword and can carry one or no value; 2. Case matches from top to bottom in order, only the first match is run; 3. Multiple conditions can be listed by commas to match the same case; 4. There is no need to manually add break, but can be forced through; 5.default is used for unmatched cases, usually placed at the end.

Usecontexttopropagatecancellationanddeadlinesacrossgoroutines,enablingcooperativecancellationinHTTPservers,backgroundtasks,andchainedcalls.2.Withcontext.WithCancel(),createacancellablecontextandcallcancel()tosignaltermination,alwaysdeferringcancel()t

Use a dedicated and reasonably configured HTTP client to set timeout and connection pools to improve performance and resource utilization; 2. Implement a retry mechanism with exponential backoff and jitter, only retry for 5xx, network errors and 429 status codes, and comply with Retry-After headers; 3. Use caches for static data such as user information (such as sync.Map or Redis), set reasonable TTL to avoid repeated requests; 4. Use semaphore or rate.Limiter to limit concurrency and request rates to prevent current limit or blocking; 5. Encapsulate the API as an interface to facilitate testing, mocking, and adding logs, tracking and other middleware; 6. Monitor request duration, error rate, status code and retry times through structured logs and indicators, combined with Op

To correctly copy slices in Go, you must create a new underlying array instead of directly assigning values; 1. Use make and copy functions: dst:=make([]T,len(src));copy(dst,src); 2. Use append and nil slices: dst:=append([]T(nil),src...); both methods can realize element-level copying, avoid sharing the underlying array, and ensure that modifications do not affect each other. Direct assignment of dst=src will cause both to refer to the same array and are not real copying.

Use the template.ParseFS and embed package to compile HTML templates into binary files. 1. Import the embed package and embed the template file into the embed.FS variable with //go:embedtemplates/.html; 2. Call template.Must(template.ParseFS(templateFS,"templates/.html")))) to parse all matching template files; 3. Render the specified in the HTTP processor through tmpl.ExecuteTemplate(w,"home.html", nil)

Go uses time.Time structure to process dates and times, 1. Format and parse the reference time "2006-01-0215:04:05" corresponding to "MonJan215:04:05MST2006", 2. Use time.Date(year, month, day, hour, min, sec, nsec, loc) to create the date and specify the time zone such as time.UTC, 3. Time zone processing uses time.LoadLocation to load the position and use time.ParseInLocation to parse the time with time zone, 4. Time operation uses Add, AddDate and Sub methods to add and subtract and calculate the interval.

AruneinGoisaUnicodecodepointrepresentedasanint32,usedtocorrectlyhandleinternationalcharacters;1.Userunesinsteadofbytestoavoidsplittingmulti-byteUnicodecharacters;2.Loopoverstringswithrangetogetrunes,notbytes;3.Convertastringto[]runetosafelymanipulate

To import local packages correctly, you need to use the Go module and follow the principle of matching directory structure with import paths. 1. Use gomodinit to initialize the module, such as gomodinitexample.com/myproject; 2. Place the local package in a subdirectory, such as mypkg/utils.go, and the package is declared as packagemypkg; 3. Import it in main.go through the full module path, such as import "example.com/myproject/mypkg"; 4. Avoid relative import, path mismatch or naming conflicts; 5. Use replace directive for packages outside the module. Just make sure the module is initialized
