Magento 2 GraphQL API : دليل المطور الشامل (2026)
تعد GraphQL API لماجنتو 2 العمود الفقري لواجهات المتاجر headless الحديثة وتطبيقات PWA وتطبيقات الهاتف المحمول. على عكس REST — التي تتطلب غالبًا جولات متعددة — تسمح GraphQL للعميل بطلب الحقول التي يحتاجها بالضبط في استدعاء واحد. يغطي هذا الدليل المخطط المضمن، المصادقة، طفرات سلة التسوق والدفع، تطوير المحللات المخصصة، وأنماط الأداء المهمة في الإنتاج.
باختصار: يعرض GraphQL في ماجنتو 2 المنتجات والفئات وسلة التسوق والدفع وبيانات العملاء من خلال مخطط typed في
/graphql. استخدم queries للقراءة، mutations للكتابة، ووسّع المخطط بمحللات مخصصة عندما لا تكفي الحقول المضمنة.
جدول المحتويات
- لماذا GraphQL لماجنتو 2؟
- نقطة النهاية والرؤوس وأول استعلام
- المخطط الأساسي: المنتجات والفئات والبحث
- طفرات سلة التسوق والدفع
- مصادقة العميل
- بناء محلل استعلام مخصص
- بناء طفرة مخصصة
- الأداء والتخزين المؤقت
- GraphQL مقابل REST: متى تستخدم ماذا
- الأسئلة الشائعة التقنية
لماذا GraphQL لماجنتو 2؟
استثمرت Adobe بكثافة في GraphQL كـ API الأساسي للعمليات الموجهة لواجهة المتجر. تظل REST متاحة لتكاملات Admin والأنظمة القديمة، لكن الأعمال الجديدة على الواجهة الأمامية — Hyvä React Checkout و PWA Studio وواجهات Next.js المخصصة — تعمل على GraphQL.
| الميزة | التفاصيل |
|---|---|
| طلب واحد | احصل على اسم المنتج وسعره وصورته ومخزونه في استدعاء واحد |
| لا استرجاع زائد | يختار العميل فقط الحقول التي يعرضها |
| مخطط typed | توثيق ذاتي عبر introspection |
| حالة السلة | نموذج token cart_id يناسب الواجهات الأمامية عديمة الحالة |
| استقرار الإصدارات | يتطور المخطط مع إهمال متوافق مع الإصدارات السابقة |
نقطة النهاية:
POST https://your-store.com/graphql
Content-Type: application/json
نقطة النهاية والرؤوس وأول استعلام
استعلام منتج أساسي
{
products(filter: { sku: { eq: "24-MB01" } }) {
items {
sku
name
price_range {
minimum_price {
regular_price {
value
currency
}
}
}
image {
url
label
}
}
}
}
أرسله باستخدام curl:
curl -X POST https://your-store.com/graphql \
-H "Content-Type: application/json" \
-d '{"query": "{ products(filter: { sku: { eq: \"24-MB01\" } }) { items { sku name } } }"}'
رأس Store (إعدادات المتاجر المتعددة)
عند تشغيل عدة طرق عرض للمتجر، مرر رأس Store:
-H "Store: default"
"
بدونه، قد يعيد ماجنتو بيانات من طريقة عرض المتجر الخاطئة — أسعار خاطئة، لغة خاطئة، عملة خاطئة.
---
## المخطط الأساسي: المنتجات والفئات والبحث
**قائمة الفئات مع الفلاتر**
```graphql
{
categoryList(filters: { url_key: { eq: "gear" } }) {
id
name
products(pageSize: 12, currentPage: 1) {
total_count
items {
sku
name
small_image { url }
price_range {
minimum_price {
final_price { value currency }
}
}
}
page_info {
current_page
total_pages
}
}
}
}
البحث بالنص الكامل
{
products(search: "backpack", pageSize: 10) {
total_count
items {
sku
name
url_key
}
}
}
"
يعتمد البحث على مفهرس `catalogsearch_fulltext` و Elasticsearch/OpenSearch. إذا أرجع البحث نتائج فارغة، أعد الفهرسة أولاً:
```bash
bin/magento indexer:reindex catalogsearch_fulltext
خيارات المنتج القابل للتكوين
{
products(filter: { sku: { eq: "MH01" } }) {
items {
sku
name
... on ConfigurableProduct {
configurable_options {
attribute_code
label
values {
value_index
label
}
}
variants {
product {
sku
name
price_range {
minimum_price {
final_price { value }
}
}
}
}
}
}
}
}
استخدم الأجزاء المضمنة (... on ConfigurableProduct) للوصول إلى الحقول الخاصة بالنوع — وهو نمط GraphQL أساسي في ماجنتو.
طفرات سلة التسوق والدفع
تستخدم سلال الضيوف cart_id (معرف عرض سعر مقنّع). سلال العملاء تستخدم token العميل الموثق.
إنشاء سلة ضيف
mutation {
createEmptyCart
}
الاستجابة:
{ "data": { "createEmptyCart": "abc123xyz" } }
إضافة منتج إلى السلة
mutation {
addProductsToCart(
cartId: "abc123xyz"
cartItems: [{ sku: "24-MB01", quantity: 1 }]
) {
cart {
items {
quantity
product {
name
sku
}
}
prices {
grand_total {
value
currency
}
}
}
}
}
دمج سلة الضيف بعد تسجيل الدخول
mutation {
mergeCarts(
source_cart_id: "abc123xyz"
destination_cart_id: "customer-cart-id"
) {
items { quantity product { sku } }
}
}
تعيين عنوان الشحن وطريقة الشحن
mutation {
setShippingAddressesOnCart(
input: {
cart_id: "abc123xyz"
shipping_addresses: [{
address: {
firstname: "John"
lastname: "Doe"
street: ["123 Main St"]
city: "Paris"
postcode: "75001"
country_code: FR
telephone: "0600000000"
}
}]
}
) {
cart {
shipping_addresses {
available_shipping_methods {
carrier_code
method_code
amount { value currency }
}
}
}
}
}
نصيحة الدفع headless: اطلب دائمًا
available_shipping_methodsوavailable_payment_methodsبعد تعيين العنوان — تعتمد الأسعار على محتويات السلة والوجهة.
مصادقة العميل
إنشاء token عميل
mutation {
generateCustomerToken(
email: "[email protected]"
password: "Password123!"
) {
token
}
}
استخدم token في الطلبات اللاحقة:
-H "Authorization: Bearer <token>"
"
تنتهي صلاحية tokens بناءً على تكوين Admin (`Stores → Configuration → Services → OAuth → Customer Token Lifetime`). القيمة الافتراضية هي ساعة واحدة — خطط لمنطق التحديث في واجهتك الأمامية.
**استعلام introspection (للمطورين فقط)**
عطّل introspection في الإنتاج للأمان. في التطوير، استكشف المخطط:
```graphql
{
__schema {
types {
name
kind
}
}
}
أو استخدم GraphQL Playground / Altair / Postman مع تمكين introspection.
بناء محلل استعلام مخصص
عندما لا يكفي المخطط المضمن، وسّعه بوحدة مخصصة.
هيكل الدليل
app/code/MagentoMastery/GraphQlDemo/
├── registration.php
├── etc/
│ ├── module.xml
│ └── schema.graphqls
└── Model/
└── Resolver/
└── HelloWorld.php
Query schema.graphqls
type Query {
helloWorld(name: String): String
@resolver(class: "MagentoMastery\\GraphQlDemo\\Model\\Resolver\\HelloWorld")
@doc(description: "Returns a greeting string")
}
فئة المحلل
<?php
declare(strict_types=1);
namespace MagentoMastery\GraphQlDemo\Model\Resolver;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
class HelloWorld implements ResolverInterface
{
public function resolve(
Field $field,
$context,
ResolveInfo $info,
?array $value = null,
?array $args = null
): string {
$name = $args['name'] ?? 'World';
return "Hello, {$name}!";
}
}
اختبر الاستعلام المخصص
{ helloWorld(name: "Magento") }
بعد النشر:
bin/magento setup:upgrade
bin/magento cache:flush
تتطلب تغييرات مخطط GraphQL مسحًا للذاكرة المؤقتة — يخزن ماجنتو المخطط المجمّع مؤقتًا.
بناء طفرة مخصصة
تتبع الطفرات نفس النمط لكنها تطبق ResolverInterface على حقل من نوع Mutation.
Mutation schema.graphqls
type Mutation {
subscribeNewsletter(email: String!): NewsletterOutput
@resolver(class: "MagentoMastery\\GraphQlDemo\\Model\\Resolver\\SubscribeNewsletter")
}
type NewsletterOutput {
success: Boolean!
message: String
}
محلل مع التحقق
<?php
declare(strict_types=1);
namespace MagentoMastery\GraphQlDemo\Model\Resolver;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
class SubscribeNewsletter implements ResolverInterface
{
public function resolve(
Field $field,
$context,
ResolveInfo $info,
?array $value = null,
?array $args = null
): array {
$email = $args['email'] ?? '';
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new GraphQlInputException(__('Invalid email address.'));
}
// Subscribe logic here...
return [
'success' => true,
'message' => 'Subscribed successfully.',
];
}
}
"
ارمِ `GraphQlInputException` لأخطاء العميل (مستوى 400) و `GraphQlAuthorizationException` لفشل المصادقة — يقوم ماجنتو بترجمتها إلى استجابات خطأ GraphQL المناسبة.
---
## الأداء والتخزين المؤقت
يمكن أن يكون GraphQL أبطأ من المتوقع إذا طلب العملاء حقولاً متداخلة كثيرة. طبّق هذه القواعد في الإنتاج:
**1. حدد عمق وتعقيد الاستعلام**
استخدم proxy عكسي أو حدود تعقيد الاستعلام المضمنة في ماجنتو (Adobe Commerce) لحظر الاستعلامات المسيئة.
**2. خزن مؤقتًا في CDN للاستعلامات المجهولة**
خزن مؤقتًا فقط الاستعلامات التي لا تتضمن tokens عميل أو معرفات سلة. استعلامات قائمة المنتجات مرشحة جيدة لـ CDN عند مفتاحها بواسطة المتجر + تجزئة الاستعلام.
**3. تجنب N+1 في المحللات المخصصة**
عند تحليل القوائم، استخدم محللات دفعة أو أدوات تحميل بيانات. المحلل البسيط الذي يحمّل نموذج منتج لكل عنصر سيدمر الأداء في صفحات الفئات.
**4. اطلب فقط ما تعرضه**
```graphql
items { sku name description { html } }
items { sku name small_image { url } price_range { minimum_price { final_price { value } } } }
5. حافظ على صحة المفهرسات
يقرأ GraphQL من جداول مسطحة مفهرسة و Elasticsearch. مفهرسات قديمة = استجابات API قديمة. راجع دليل المفهرسات للصيانة.
GraphQL مقابل REST: متى تستخدم ماذا
| حالة الاستخدام | API الموصى به |
|---|---|
| واجهة متجر / PWA / تطبيق جوال | GraphQL |
| تكاملات الإدارة (طلبات، استيراد كتالوج) | REST (Async Bulk API) |
| مزامنة ERP خارجية | REST |
| سلة/دفع في الوقت الفعلي | GraphQL |
| تكاملات قديمة | REST |
اتجاه Adobe واضح: GraphQL للعميل، REST للعمليات الخلفية المجمعة.
الأسئلة الشائعة التقنية
أين يُعرف مخطط GraphQL؟
ملفات المخطط الأساسية موجودة في etc/schema.graphqls لكل وحدة. يدمجها ماجنتو في وقت التشغيل. تضيف الوحدات المخصصة ملف etc/schema.graphqls الخاص بها.
هل يمكنني استخدام GraphQL في لوحة الإدارة؟
صُمم GraphQL لعمليات واجهة المتجر. تستخدم وظائف الإدارة REST أو واجهة المستخدم الإدارية — لا تعرض عمليات الإدارة عبر GraphQL مخصص بدون فحوصات ACL صارمة.
كيف أصحح أخطاء GraphQL؟
فعّل وضع المطور وتحقق من var/log/exception.log. يعيد GraphQL الأخطاء في مصفوفة errors من استجابة JSON مع حقلي message و category.
هل يستبدل GraphQL الدفع بـ Knockout.js؟
ليس تلقائيًا. لا يزال دفع Luma قائمًا على Knockout. يتطلب الدفع headless واجهة أمامية تستهلك طفرات GraphQL (React, Vue, Hyvä Checkout, إلخ). راجع دليل الدفع للعمل مع Knockout.js أو بناء بديل headless.
هل GraphQL متاح في Magento Open Source؟
نعم. GraphQL جزء من Magento Open Source منذ 2.3.x. بعض الميزات المتقدمة (حدود تعقيد الاستعلام، معاينات staging) مخصصة لـ Adobe Commerce فقط.
الخاتمة
GraphQL هي طبقة API القياسية لواجهات متاجر ماجنتو 2 الحديثة. أتقن أولاً مخطط المنتجات وسلة التسوق المضمن، ثم وسّعه بمحللات مخصصة عندما تتطلب ذلك منطق الأعمال. حافظ على استعلاماتك خفيفة، ومفهرساتك محدثة، وtokens المصادقة جديدة — وستبقى واجهة متجرك headless سريعة وموثوقة.
هل تبني واجهة متجر headless لماجنتو 2 أو تحتاج نقاط نهاية GraphQL مخصصة؟ اتصل بي لمراجعات الهندسة المعمارية، وحدات مخصصة ، وتحسين الأداء.