واجهات GraphQL

مخطط GraphQL ونظام الأنواع

20 دقيقة الدرس 2 من 35

فهم مخطط GraphQL

مخطط GraphQL هو العقد بين العميل والخادم. يحدد الاستعلامات التي يمكن للعملاء إجراؤها، وأنواع البيانات التي يمكن جلبها، والعلاقات بين الأنواع. تحدد كل خدمة GraphQL مخططاً يصف بشكل كامل مجموعة البيانات المحتملة التي يمكنك الاستعلام عنها في تلك الخدمة.

مفهوم رئيسي: تتم كتابة المخطط باستخدام لغة تعريف المخطط (SDL)، وهي بناء جملة قابل للقراءة البشرية لتحديد مخططات GraphQL.

لغة تعريف المخطط (SDL)

SDL هي لغة بسيطة وبديهية لتحديد مخطط GraphQL الخاص بك. إليك مثال أساسي:

type User { id: ID! name: String! email: String! age: Int isActive: Boolean! } type Query { user(id: ID!): User users: [User!]! }

يحدد هذا المخطط نوع User بعدة حقول ونوع Query بعمليتي استعلام.

الأنواع القياسية

تأتي GraphQL مع مجموعة من الأنواع القياسية الافتراضية التي تمثل القيم البدائية:

  • Int: عدد صحيح موقع 32 بت (مثل 42، -10)
  • Float: قيمة نقطة عائمة مزدوجة الدقة موقعة (مثل 3.14، -0.5)
  • String: تسلسل أحرف UTF-8 (مثل "Hello"، "مرحباً")
  • Boolean: صح أو خطأ
  • ID: معرف فريد، يتم تسلسله كسلسلة نصية ولكن غير مخصص للقراءة البشرية
type Product { id: ID! # معرف فريد name: String! # اسم المنتج price: Float! # السعر كرقم عشري quantity: Int! # الكمية في المخزون inStock: Boolean! # حالة التوفر }
أفضل ممارسة: استخدم نوع ID للمعرفات الفريدة حتى لو تم تسلسلها كسلاسل نصية. هذا يوصل النية ويسمح لعملاء GraphQL بالتخزين المؤقت وتطبيع البيانات بشكل أكثر فعالية.

أنواع الكائنات

أنواع الكائنات هي النوع الأكثر شيوعاً الذي ستحدده في مخططك. تمثل مجموعة من الحقول، حيث يكون لكل حقل نوع محدد:

type Author { id: ID! name: String! email: String! books: [Book!]! } type Book { id: ID! title: String! isbn: String publishedYear: Int! author: Author! }

لاحظ كيف يشير Author و Book إلى بعضهما البعض، مما يخلق علاقة بين النوعين.

أنواع التعداد

التعدادات هي أنواع قياسية خاصة تقيد حقلاً بمجموعة معينة من القيم المسموح بها:

enum Role { ADMIN USER MODERATOR GUEST } enum OrderStatus { PENDING PROCESSING SHIPPED DELIVERED CANCELLED } type User { id: ID! name: String! role: Role! } type Order { id: ID! status: OrderStatus! total: Float! }
مهم: يتم تسلسل قيم التعداد كسلاسل نصية في JSON، لكن GraphQL تتحقق من استخدام قيم التعداد المحددة فقط.

أنواع القوائم

تمثل القوائم تسلسلاً مرتباً من القيم. يتم الإشارة إليها عن طريق لف نوع في أقواس مربعة:

type User { id: ID! name: String! hobbies: [String!]! # قائمة من السلاسل النصية friends: [User!]! # قائمة من كائنات المستخدم tags: [String] # قائمة قابلة للقيمة الفارغة مع عناصر قابلة للقيمة الفارغة } type Query { users: [User!]! # تُرجع مصفوفة من المستخدمين searchUsers(query: String!): [User] # قد تُرجع null أو مصفوفة فارغة }

معدل النوع غير الفارغ

بشكل افتراضي، جميع الأنواع في GraphQL قابلة للقيمة الفارغة. تجعل علامة التعجب (!) نوعاً غير قابل للقيمة الفارغة:

type User { id: ID! # لا يمكن أن يكون فارغاً name: String! # لا يمكن أن يكون فارغاً email: String # يمكن أن يكون فارغاً age: Int # يمكن أن يكون فارغاً friends: [User!]! # المصفوفة لا يمكن أن تكون فارغة، العناصر لا يمكن أن تكون فارغة tags: [String!] # المصفوفة يمكن أن تكون فارغة، لكن العناصر لا يمكن أن تكون فارغة posts: [Post]! # المصفوفة لا يمكن أن تكون فارغة، لكن العناصر يمكن أن تكون فارغة comments: [Comment] # كل من المصفوفة والعناصر يمكن أن تكون فارغة }
تحذير: كن حذراً مع معدلات القيمة غير الفارغة على القوائم. [User!]! يعني أن القائمة لا يمكن أن تكون فارغة ولا يمكن لأي عنصر أن يكون فارغاً. إذا كان أي عنصر فارغاً، فسيكون الحقل بأكمله فارغاً.

مجموعات معدلات الأنواع

فهم المجموعات المختلفة من معدلات القائمة والقيمة غير الفارغة أمر بالغ الأهمية:

type Examples { # يمكن أن تُرجع: null، []، ["a"، "b"]، ["a"، null] example1: [String] # يمكن أن تُرجع: []، ["a"، "b"]، ["a"، null] # لا يمكن أن تُرجع: null example2: [String]! # يمكن أن تُرجع: null، []، ["a"، "b"] # لا يمكن أن تُرجع: ["a"، null] example3: [String!] # يمكن أن تُرجع: []، ["a"، "b"] # لا يمكن أن تُرجع: null، ["a"، null] example4: [String!]! }

أنواع الإدخال

أنواع الإدخال هي أنواع كائنات خاصة تُستخدم لتمرير كائنات معقدة كوسائط:

input CreateUserInput { name: String! email: String! age: Int role: Role! } input UpdateUserInput { name: String email: String age: Int role: Role } type Mutation { createUser(input: CreateUserInput!): User! updateUser(id: ID!, input: UpdateUserInput!): User! }
أفضل ممارسة: استخدم أنواع الإدخال للطفرات بدلاً من إدراج العديد من الوسائط الفردية. هذا يجعل مخططك أكثر قابلية للصيانة وأسهل في التطور.

أنواع الواجهة

تسمح لك الواجهات بتحديد مجموعة من الحقول التي يجب أن تتضمنها أنواع متعددة:

interface Node { id: ID! createdAt: String! } type User implements Node { id: ID! createdAt: String! name: String! email: String! } type Post implements Node { id: ID! createdAt: String! title: String! content: String! author: User! } type Query { node(id: ID!): Node }

أنواع الاتحاد

تسمح أنواع الاتحاد لحقل بإرجاع أحد أنواع الكائنات المتعددة:

union SearchResult = User | Post | Comment type Query { search(query: String!): [SearchResult!]! } # في الاستعلام، تستخدم الأجزاء للوصول إلى الحقول: query { search(query: "graphql") { ... on User { name email } ... on Post { title author { name } } ... on Comment { text author { name } } } }
تمرين: صمم مخططاً لنظام مدونة بسيط مع المتطلبات التالية:
  • يمكن للمستخدمين كتابة منشورات وتعليقات
  • المنشورات لها عنوان ومحتوى وحالة (مسودة، منشور، مؤرشف) وعلامات
  • التعليقات تنتمي إلى المنشورات ولها نص وتقييم اختياري (1-5)
  • قم بتضمين الاستعلامات والطفرات المناسبة
  • استخدم معدلات الأنواع المناسبة للحقول القابلة للقيمة الفارغة وغير القابلة للقيمة الفارغة

ملخص

في هذا الدرس، تعلمت عن نظام أنواع GraphQL، بما في ذلك الأنواع القياسية وأنواع الكائنات والتعدادات والقوائم ومعدلات الأنواع. المخطط هو أساس واجهة برمجة تطبيقات GraphQL الخاصة بك - فهو يحدد العقد بين العميل والخادم ويمكّن من أدوات قوية مثل الإكمال التلقائي والتحقق.