การสร้างสคีมาด้วย graphql-php
กำหนดชนิดข้อมูลและสคีมาด้วย webonyx/graphql-php
การสร้างสคีมาด้วย graphql-php เป็นบทเรียน PHP Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน PHP Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน
graphql-php: การใช้งานอ้างอิง
webonyx/graphql-php คือพอร์ต PHP โดยพฤตินัยของการใช้งานอ้างอิง GraphQL ซึ่งมีระบบชนิดข้อมูล ตัวแยกวิเคราะห์ ตัวตรวจสอบความถูกต้อง และตัวดำเนินการให้คุณ คุณกำหนด schema ได้ทั้งแบบ ใช้โค้ดโปรแกรม (ออบเจ็กต์ PHP) หรือจาก SDL (แนวทางกำหนด schema ก่อน) ในบทเรียนนี้ เราจะสร้าง schema ด้วยตนเอง เพื่อให้คุณเข้าใจอย่างชัดเจนว่าแต่ละส่วนทำหน้าที่อะไร
composer require webonyx/graphql-phpสเกลาร์และรีจิสทรีชนิดข้อมูล
ค่าทุกค่าใน GraphQL จะลงท้ายที่ สเกลาร์ เช่น Int, Float, String, Boolean, ID ใน graphql-php ค่าเหล่านี้อยู่บนส่วนหน้าสำหรับเข้าถึง Type เนื่องจากชนิดออบเจ็กต์อ้างอิงถึงกันเองและอ้างอิงถึงตัวเอง รูปแบบที่ใช้กันทั่วไปคือ TypeRegistry แบบคงที่ ซึ่งจดจำชนิดข้อมูลแต่ละชนิดไว้ เพื่อให้สร้างแต่ละชนิดเพียงครั้งเดียว
<?php
use GraphQL\Type\Definition\Type;
// Built-in scalars, returned as singletons:
var_dump(Type::int()->name); // "Int"
var_dump(Type::string()->name); // "String"
var_dump(Type::id()->name); // "ID"
var_dump(Type::nonNull(Type::string())->toString()); // "String!"
การกำหนด ObjectType
ObjectType มี name และแผนผัง fields แต่ละฟิลด์จะประกาศ type และอาจมีฟังก์ชันเรียกกลับ resolve หากไม่ระบุ resolve graphql-php จะใช้รีโซลเวอร์เริ่มต้น ซึ่งอ่านคีย์อาร์เรย์หรือพร็อพเพอร์ตี/เมธอดสำหรับอ่านค่าที่ตรงกันจากค่าหลัก
<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
$postType = new ObjectType([
'name' => 'Post',
'fields' => [
'id' => Type::nonNull(Type::id()),
'title' => Type::nonNull(Type::string()),
'body' => Type::string(),
],
]);
การห่อชนิดแบบไม่เป็นค่าว่างและรายการ
ชนิดที่ห่อหุ้มใช้แสดงความเป็นค่าว่างและจำนวนสมาชิก:
Type::nonNull(T)→T!(ไม่เป็นค่าว่างเลย)Type::listOf(T)→[T](เป็นรายการที่อาจเป็นค่าว่าง และสมาชิกภายในก็อาจเป็นค่าว่างได้)[Post!]!= รายการที่ไม่เป็นค่าว่างและมีโพสต์ที่ไม่เป็นค่าว่างทุกตัว →nonNull(listOf(nonNull($postType)))
ต้องกำหนดส่วนนี้ให้ถูกต้อง เพราะนี่คือสัญญาเรื่องค่าว่างของ schema ที่ให้ไว้กับไคลเอ็นต์
<?php
use GraphQL\Type\Definition\Type;
// [Post!]! -- a required list whose elements are never null
$wrapped = Type::nonNull(Type::listOf(Type::nonNull(Type::string())));
echo $wrapped->toString(), "\n"; // [String!]!
ฟิลด์แบบประเมินภายหลังช่วยแก้การอ้างอิงแบบวนรอบ
User มี posts และ Post มี author (ซึ่งเป็น User) หากต้องการสร้างชนิดข้อมูลที่อ้างอิงถึงกัน ให้ส่ง fields เป็น โคลเชอร์ แทนอาร์เรย์ โคลเชอร์จะทำงานภายหลังเมื่อชนิดข้อมูลทั้งสองมีอยู่แล้ว จึงหลีกเลี่ยงปัญหาว่าอะไรควรถูกสร้างก่อน
<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
class Types {
private static array $cache = [];
public static function user(): ObjectType {
return self::$cache['User'] ??= new ObjectType([
'name' => 'User',
'fields' => fn() => [ // lazy!
'id' => Type::nonNull(Type::id()),
'name' => Type::nonNull(Type::string()),
'posts' => Type::listOf(self::post()),
],
]);
}
public static function post(): ObjectType {
return self::$cache['Post'] ??= new ObjectType([
'name' => 'Post',
'fields' => fn() => [
'id' => Type::nonNull(Type::id()),
'title' => Type::nonNull(Type::string()),
'author' => self::user(), // back-reference
],
]);
}
}
อาร์กิวเมนต์ของฟิลด์
ฟิลด์สามารถรับอาร์กิวเมนต์ได้ ให้ประกาศอาร์กิวเมนต์ไว้ใต้คีย์ args โดยอาร์กิวเมนต์เหล่านี้จะเข้ามาเป็นพารามิเตอร์ตัวที่สอง ($args) ของรีโซลเวอร์ อาร์กิวเมนต์เองก็มีชนิดข้อมูลได้ อาจกำหนดให้ไม่เป็นค่าว่าง และอาจมีค่า defaultValue ได้
<?php
use GraphQL\Type\Definition\Type;
$userField = [
'type' => Type::string(),
'args' => [
'id' => Type::nonNull(Type::id()),
'locale' => ['type' => Type::string(), 'defaultValue' => 'en'],
],
'resolve' => fn($root, array $args) => "user {$args['id']} ({$args['locale']})",
];
ชนิด Query ราก
ทุก schema ต้องมีชนิด Query ราก ซึ่งเป็นจุดเริ่มต้นที่ไคลเอ็นต์ใช้เรียกข้อมูล ในที่นี้เราจะเปิดเผยฟิลด์ hello เพียงฟิลด์เดียว เพื่อให้สามารถดำเนินการได้ตั้งแต่ต้นจนจบ อาร์กิวเมนต์ตัวแรกของรีโซลเวอร์รากคือ rootValue ของ schema ซึ่งมักเป็น null
<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'hello' => [
'type' => Type::string(),
'args' => ['name' => Type::nonNull(Type::string())],
'resolve' => fn($root, array $args) => 'Hello, ' . $args['name'],
],
],
]);
การประกอบและเรียกใช้ Schema
ห่อชนิดคิวรีไว้ใน Schema แล้วส่งสตริงคิวรีผ่าน GraphQL::executeQuery() ออบเจ็กต์ผลลัพธ์จะแปลงเป็นอาร์เรย์ { data, errors } ตามรูปแบบมาตรฐานผ่าน toArray()
<?php
require 'vendor/autoload.php';
use GraphQL\GraphQL;
use GraphQL\Type\Schema;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'hello' => [
'type' => Type::string(),
'args' => ['name' => Type::nonNull(Type::string())],
'resolve' => fn($root, $args) => 'Hello, ' . $args['name'],
],
],
]);
$schema = new Schema(['query' => $queryType]);
$result = GraphQL::executeQuery($schema, '{ hello(name: "Ada") }');
echo json_encode($result->toArray());
// {"data":{"hello":"Hello, Ada"}}
ทางเลือกแบบกำหนด Schema ก่อนด้วย BuildSchema
หากคุณต้องการใช้ SDL, BuildSchema::build() จะแยกวิเคราะห์สตริง schema ให้เป็น schema ที่เรียกใช้ได้ จากนั้นคุณจึงผูกรีโซลเวอร์แยกต่างหาก เช่น ฟังก์ชันเรียกกลับสำหรับรีโซลเวอร์ของฟิลด์ วิธีนี้ทำให้คำจำกัดความชนิดข้อมูลยังคงเป็นแบบประกาศ ขณะที่ตรรกะยังอยู่ใน PHP
<?php
use GraphQL\Utils\BuildSchema;
$sdl = <<<'GQL'
type Query {
hello(name: String!): String
}
GQL;
$schema = BuildSchema::build($sdl);
// Provide resolvers via the executeQuery $fieldResolver argument
// or with a type config decorator.
ตรวจสอบความถูกต้องก่อนเผยแพร่
graphql-php จะตรวจสอบคิวรีที่รับเข้ามากับ schema โดยอัตโนมัติก่อนดำเนินการ คุณยังสามารถตรวจสอบได้ว่า schema เองมีความสอดคล้องภายในหรือไม่ในเวลาสร้าง/ใน CI ด้วย $schema->assertValid() เพื่อค้นหาการพิมพ์ผิดและการอ้างอิงที่เสียหายก่อนนำไปใช้งาน ไม่ใช่รอจนถึงเวลารับคำขอ
<?php
use GraphQL\Type\Schema;
/** @var Schema $schema */
$schema->assertValid(); // throws InvariantViolation on a broken schema
echo "schema OK\n";
ค่าแจกแจงและสเกลาร์กำหนดเอง
นอกเหนือจากออบเจ็กต์แล้ว ชนิดข้อมูลอีกสองแบบนี้ช่วยเติมเต็ม schema ส่วนใหญ่ EnumType จำกัดฟิลด์ให้รับค่าแบบมีชื่อจากชุดที่กำหนดไว้เท่านั้น ส่วน CustomScalarType เปิดให้คุณกำหนดสเกลาร์เฉพาะโดเมน เช่น DateTime และอีเมล ด้วยตรรกะ serialize/parseValue/parseLiteral ของคุณเอง เพื่อให้ตรวจสอบและปรับรูปแบบค่าที่ขอบเขตระบบ
<?php
use GraphQL\Type\Definition\EnumType;
$statusEnum = new EnumType([
'name' => 'PostStatus',
'values' => [
'DRAFT' => ['value' => 0],
'PUBLISHED' => ['value' => 1],
'ARCHIVED' => ['value' => 2],
],
]);
// A field typed as $statusEnum only accepts DRAFT/PUBLISHED/ARCHIVED.
ตรวจสอบความเข้าใจ
เหตุใดจึงส่ง fields เป็นโคลเชอร์
ทบทวน
คุณได้สร้าง schema ตั้งแต่พื้นฐานดังนี้:
- สเกลาร์และชนิดที่ห่อหุ้ม (
nonNull,listOf) ใช้แสดงสัญญาเรื่องค่าว่าง/จำนวนสมาชิก ObjectTypeที่มีแผนผังฟิลด์ (หรือโคลเชอร์แบบประเมินภายหลัง) ใช้กำหนดโครงสร้างข้อมูล- รีจิสทรีชนิดข้อมูลที่จดจำค่าจะจัดการการอ้างอิงแบบวนรอบ
- ฟิลด์รับ
argsที่มีการระบุชนิดข้อมูล และชนิดQueryรากคือจุดเริ่มต้น GraphQL::executeQuery()ใช้ดำเนินการ ส่วนassertValid()ช่วยป้องกันปัญหาใน schema ระหว่าง CI
ถัดไป: รีโซลเวอร์ มิวเทชัน และการสมัครรับข้อมูล
คำถามที่พบบ่อย
บทเรียน “การสร้างสคีมาด้วย graphql-php” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การสร้างสคีมาด้วย graphql-php” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส PHP Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การสร้างสคีมาด้วย graphql-php”
กำหนดชนิดข้อมูลและสคีมาด้วย webonyx/graphql-php คุณปฏิบัติ PHP Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน PHP Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน PHP Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “การสร้างสคีมาด้วย graphql-php” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน PHP Academy นี้ได้ไหม
ได้ บทเรียน PHP Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- GraphQL เทียบกับ REST
- การสร้างสคีมาด้วย graphql-php
- ตัวแก้ไข การกลายพันธุ์ และการสมัครรับข้อมูล
- ประสิทธิภาพ: N+1 และ DataLoader