عميل GraphQL مكتوب بلغة PHP والذي يوفر فئات منشئ استعلام بسيطة جدًا، لكنها قوية، مما يجعل عملية التفاعل مع خادم GraphQL عملية بسيطة جدًا.
هناك ثلاث طرق أساسية لاستخدام هذه الحزمة لإنشاء استعلامات GraphQL الخاصة بك:
Query
ديناميكيًا. إنه تصميم ليتم استخدامه في الحالات التي يتم فيها إنشاء الاستعلام بطريقة ديناميكية.قم بتشغيل الأمر التالي لتثبيت الحزمة باستخدام الملحن:
$ composer require gmostafa/php-graphql-client
لتجنب متاعب الاضطرار إلى كتابة أي استعلامات والتفاعل فقط مع كائنات PHP التي تم إنشاؤها من مخطط API الخاص بك، قم بزيارة مستودع PHP GraphQL OQM
$ gql = ( new Query ( ' companies ' ))
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
سيؤدي هذا الاستعلام البسيط إلى استرجاع جميع الشركات التي تعرض أسمائها وأرقامها التسلسلية.
يتم تمثيل الاستعلام المقدم في المثال السابق في "النموذج المختصر". يتضمن النموذج المختصر كتابة عدد أقل من أسطر التعليمات البرمجية مما يؤدي إلى تسريع عملية كتابة الاستعلامات. فيما يلي مثال للنموذج الكامل لنفس الاستعلام المكتوب في المثال السابق.
$ gql = ( new Query ())
-> setSelectionSet (
[
( new Query ( ' companies ' ))
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
)
]
);
كما هو موضح في المثال، فإن النموذج المختصر أسهل في القراءة والكتابة، ويفضل استخدامه عمومًا مقارنة بالنموذج الكامل.
لا ينبغي استخدام النموذج الكامل إلا إذا تعذر تمثيل الاستعلام في النموذج المختصر، الذي يحتوي على حالة واحدة فقط، عندما نريد تشغيل استعلامات متعددة في نفس الكائن.
$ gql = ( new Query ())
-> setSelectionSet (
[
( new Query ( ' companies ' ))
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
),
( new Query ( ' countries ' ))
-> setSelectionSet (
[
' name ' ,
' code ' ,
]
)
]
);
يقوم هذا الاستعلام باسترداد جميع الشركات والدول التي تعرض بعض حقول البيانات لكل منها. يقوم بشكل أساسي بتشغيل استعلامين مستقلين (أو أكثر إذا لزم الأمر) في غلاف كائن استعلام واحد.
تتطلب كتابة استعلامات متعددة كتابة كائن الاستعلام في النموذج الكامل لتمثيل كل استعلام كحقل فرعي ضمن كائن الاستعلام الأصلي.
$ gql = ( new Query ( ' companies ' ))
-> setSelectionSet (
[
' name ' ,
' serialNumber ' ,
( new Query ( ' branches ' ))
-> setSelectionSet (
[
' address ' ,
( new Query ( ' contracts ' ))
-> setSelectionSet ([ ' date ' ])
]
)
]
);
يعد هذا الاستعلام أكثر تعقيدًا، حيث لا يسترد الحقول العددية فحسب، بل يسترد حقول الكائنات أيضًا. يقوم هذا الاستعلام بإرجاع جميع الشركات مع عرض أسمائها وأرقامها التسلسلية، ولكل شركة جميع فروعها مع عرض عنوان الفرع، ولكل عنوان يقوم باسترجاع جميع العقود المرتبطة بهذا العنوان مع عرض تواريخها.
$ gql = ( new Query ( ' companies ' ))
-> setArguments ([ ' name ' => ' Tech Co. ' , ' first ' => 3 ])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
لا يقوم هذا الاستعلام باسترداد جميع الشركات عن طريق إضافة الوسائط. سيؤدي هذا الاستعلام إلى استرجاع أول 3 شركات تحمل اسم "Tech Co." مع عرض أسمائها وأرقامها التسلسلية.
$ gql = ( new Query ( ' companies ' ))
-> setArguments ([ ' serialNumbers ' => [ 159 , 260 , 371 ]])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
يعد هذا الاستعلام حالة خاصة للاستعلام عن الوسائط. في هذا المثال، سيقوم الاستعلام باسترداد فقط الشركات ذات الرقم التسلسلي في إحدى الأرقام 159 و260 و371، مع عرض الاسم والرقم التسلسلي.
$ gql = ( new Query ( ' companies ' ))
-> setArguments ([ ' filter ' => new RawObject ( ' {name_starts_with: "Face"} ' )])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
يعد هذا الاستعلام حالة خاصة أخرى لاستعلام الوسائط. في هذا المثال، نقوم بتعيين "مرشح" كائن إدخال مخصص مع بعض القيم للحد من الشركات التي يتم إرجاعها. نحن نقوم بتعيين عامل التصفية "name_starts_with" بالقيمة "Face". سيؤدي هذا الاستعلام إلى استرداد الشركات التي تبدأ أسماؤها بعبارة "وجه" فقط.
يتم استخدام فئة RawObject التي يتم إنشاؤها لإدخال السلسلة في الاستعلام كما هو. مهما كانت السلسلة التي يتم إدخالها في مُنشئ RawObject سيتم وضعها في الاستعلام كما هي بدون أي تنسيق مخصص يتم إجراؤه عادةً بواسطة فئة الاستعلام.
$ gql = ( new Query ( ' companies ' ))
-> setVariables (
[
new Variable ( ' name ' , ' String ' , true ),
new Variable ( ' limit ' , ' Int ' , false , 5 )
]
)
-> setArguments ([ ' name ' => ' $name ' , ' first ' => ' $limit ' ])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
يوضح هذا الاستعلام كيف يمكن استخدام المتغيرات في هذه الحزمة للسماح بالطلبات الديناميكية التي يتم تمكينها بواسطة معايير GraphQL.
فئة المتغير هي فئة غير قابلة للتغيير تمثل متغيرًا في معايير GraphQL. يتلقى منشئه 4 وسيطات:
$ gql = ( new Query ())
-> setSelectionSet (
[
( new Query ( ' companies ' , ' TechCo ' ))
-> setArguments ([ ' name ' => ' Tech Co. ' ])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
),
( new Query ( ' companies ' , ' AnotherTechCo ' ))
-> setArguments ([ ' name ' => ' A.N. Other Tech Co. ' ])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
)
]
);
يمكن تعيين اسم مستعار في الوسيطة الثانية لمنشئ الاستعلام للمناسبات التي يلزم فيها استرداد نفس الكائن عدة مرات باستخدام وسائط مختلفة.
$ gql = ( new Query ( ' companies ' ))
-> setAlias ( ' CompanyAlias ' )
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
يمكن أيضًا تعيين الاسم المستعار عبر طريقة الضبط.
عند الاستعلام عن حقل يُرجع نوع واجهة، قد تحتاج إلى استخدام الأجزاء المضمنة للوصول إلى البيانات الموجودة على النوع الملموس الأساسي.
يوضح هذا المثال كيفية إنشاء أجزاء مضمّنة باستخدام هذه الحزمة:
$ gql = new Query ( ' companies ' );
$ gql -> setSelectionSet (
[
' serialNumber ' ,
' name ' ,
( new InlineFragment ( ' PrivateCompany ' ))
-> setSelectionSet (
[
' boardMembers ' ,
' shareholders ' ,
]
),
]
);
يمكن استخدام فئة QueryBuilder لإنشاء كائنات الاستعلام بشكل ديناميكي، وهو ما قد يكون مفيدًا في بعض الحالات. إنه يعمل بشكل مشابه جدًا لفئة الاستعلام، لكن مبنى الاستعلام مقسم إلى خطوات.
هذه هي الطريقة التي يمكن بها إنشاء مثال "الاستعلام باستخدام وسيطة كائن الإدخال" باستخدام QueryBuilder:
$ builder = ( new QueryBuilder ( ' companies ' ))
-> setVariable ( ' namePrefix ' , ' String ' , true )
-> setArgument ( ' filter ' , new RawObject ( ' {name_starts_with: $namePrefix} ' ))
-> selectField ( ' name ' )
-> selectField ( ' serialNumber ' );
$ gql = $ builder -> getQuery ();
كما هو الحال مع فئة الاستعلام، يمكن تعيين اسم مستعار باستخدام وسيطة المنشئ الثاني.
$ builder = ( new QueryBuilder ( ' companies ' , ' CompanyAlias ' ))
-> selectField ( ' name ' )
-> selectField ( ' serialNumber ' );
$ gql = $ builder -> getQuery ();
أو عن طريق طريقة الضبط
$ builder = ( new QueryBuilder ( ' companies ' ))
-> setAlias ( ' CompanyAlias ' )
-> selectField ( ' name ' )
-> selectField ( ' serialNumber ' );
$ gql = $ builder -> getQuery ();
تمامًا مثل فئة الاستعلام، يمكن كتابة فئة QueryBuilder بشكل كامل لتمكين كتابة استعلامات متعددة ضمن كائن منشئ استعلام واحد. فيما يلي مثال لكيفية استخدام النموذج الكامل مع QueryBuilder:
$ builder = ( new QueryBuilder ())
-> setVariable ( ' namePrefix ' , ' String ' , true )
-> selectField (
( new QueryBuilder ( ' companies ' ))
-> setArgument ( ' filter ' , new RawObject ( ' {name_starts_with: $namePrefix} ' ))
-> selectField ( ' name ' )
-> selectField ( ' serialNumber ' )
)
-> selectField (
( new QueryBuilder ( ' company ' ))
-> setArgument ( ' serialNumber ' , 123 )
-> selectField ( ' name ' )
);
$ gql = $ builder -> getQuery ();
يعد هذا الاستعلام امتدادًا للاستعلام الموجود في المثال السابق. تقوم بإرجاع جميع الشركات التي تبدأ ببادئة اسم وإرجاع الشركة بالرقم serialNumber
بقيمة 123، وكلاهما في نفس الاستجابة.
يمكن إنشاء كائن العميل بسهولة من خلال توفير عنوان URL لنقطة نهاية GraphQL.
يتلقى منشئ العميل أيضًا مصفوفة "authorizationHeaders" اختيارية، والتي يمكن استخدامها لإضافة رؤوس ترخيص لجميع الطلبات التي يتم إرسالها إلى خادم GraphQL.
مثال:
$ client = new Client (
' http://api.graphql.com ' ,
[ ' Authorization ' => ' Basic xyz ' ]
);
يتلقى منشئ العميل أيضًا مصفوفة "httpOptions" اختيارية، والتي تتجاوز "authorizationHeaders" ويمكن استخدامها لإضافة خيارات طلب Guzzle HTTP Client المخصصة.
مثال:
$ client = new Client (
' http://api.graphql.com ' ,
[],
[
' connect_timeout ' => 5 ,
' timeout ' => 5 ,
' headers ' => [
' Authorization ' => ' Basic xyz '
'User-Agent' => ' testing/1.0 ' ,
],
' proxy ' => [
' http ' => ' tcp://localhost:8125 ' , // Use this proxy with "http"
' https ' => ' tcp://localhost:9124 ' , // Use this proxy with "https",
' no ' => [ ' .mit.edu ' , ' foo.com ' ] // Don't use a proxy with these
],
' cert ' => [ ' /path/server.pem ' , ' password ' ]
. . .
]
);
من الممكن استخدام عميل HTTP الذي تم تكوينه مسبقًا والذي يقوم بتنفيذ واجهة PSR-18.
مثال:
$ client = new Client (
' http://api.graphql.com ' ,
[],
[],
$ myHttpClient
);
تشغيل الاستعلام مع عميل GraphQL والحصول على النتائج في بنية الكائن:
$ results = $ client -> runQuery ( $ gql );
$ results -> getData ()-> companies [ 0 ]-> branches ;
أو الحصول على النتائج في بنية الصفيف:
$ results = $ client -> runQuery ( $ gql , true );
$ results -> getData ()[ ' companies ' ][ 1 ][ ' branches ' ][ ' address ' ];
يتطلب تشغيل الاستعلامات التي تحتوي على متغيرات تمرير مصفوفة ترابطية تقوم بتعيين أسماء المتغيرات (المفاتيح) إلى القيم المتغيرة (القيم) إلى أسلوب runQuery
. هنا مثال:
$ gql = ( new Query ( ' companies ' ))
-> setVariables (
[
new Variable ( ' name ' , ' String ' , true ),
new Variable ( ' limit ' , ' Int ' , false , 5 )
]
)
-> setArguments ([ ' name ' => ' $name ' , ' first ' => ' $limit ' ])
-> setSelectionSet (
[
' name ' ,
' serialNumber '
]
);
$ variablesArray = [ ' name ' => ' Tech Co. ' , ' first ' => 5 ];
$ results = $ client -> runQuery ( $ gql , true , $ variablesArray );
تتبع الطفرات نفس قواعد الاستعلامات في GraphQL، فهي تحدد الحقول على الكائنات التي تم إرجاعها، وتستقبل الوسائط، ويمكن أن تحتوي على حقول فرعية.
فيما يلي مثال نموذجي حول كيفية إنشاء الطفرات وتشغيلها:
$ mutation = ( new Mutation ( ' createCompany ' ))
-> setArguments ([ ' companyObject ' => new RawObject ( ' {name: "Trial Company", employees: 200} ' )])
-> setSelectionSet (
[
' _id ' ,
' name ' ,
' serialNumber ' ,
]
);
$ results = $ client -> runQuery ( $ mutation );
يمكن للعميل تشغيل الطفرات بنفس طريقة تشغيل الاستعلامات.
يمكن أن تستخدم الطفرات المتغيرات بنفس الطريقة التي تستخدمها الاستعلامات. فيما يلي مثال على كيفية استخدام المتغيرات لتمرير كائنات الإدخال إلى خادم GraphQL ديناميكيًا:
$ mutation = ( new Mutation ( ' createCompany ' ))
-> setVariables ([ new Variable ( ' company ' , ' CompanyInputObject ' , true )])
-> setArguments ([ ' companyObject ' => ' $company ' ]);
$ variables = [ ' company ' => [ ' name ' => ' Tech Company ' , ' type ' => ' Testing ' , ' size ' => ' Medium ' ]];
$ client -> runQuery (
$ mutation , true , $ variables
);
هذه هي الطفرة الناتجة والمتغيرات التي مرت معها:
mutation( $ company : CompanyInputObject!) {
createCompany (companyObject: $ company )
}
{"company":{"name":"Tech Company", " type " :"Testing", " size " :"Medium"}}
GraphQL Pokemon عبارة عن واجهة برمجة تطبيقات عامة رائعة جدًا لـ GraphQL متاحة لاسترداد بيانات Pokemon. واجهة برمجة التطبيقات (API) متاحة بشكل عام على الويب، وسنستخدمها لعرض قدرات هذا العميل.
رابط جيثب ريبو: https://github.com/lucasbento/graphql-pokemon
رابط واجهة برمجة التطبيقات: https://graphql-pokemon.now.sh/
يسترد هذا الاستعلام تطورات أي بوكيمون وهجماته:
query( $ name : String!) {
pokemon (name: $ name ) {
id
number
name
evolutions {
id
number
name
weight {
minimum
maximum
}
attacks {
fast {
name
type
damage
}
}
}
}
}
هذه هي الطريقة التي يمكن بها كتابة هذا الاستعلام باستخدام فئة الاستعلام وتشغيله باستخدام العميل:
$ client = new Client (
' https://graphql-pokemon.now.sh/ '
);
$ gql = ( new Query ( ' pokemon ' ))
-> setVariables ([ new Variable ( ' name ' , ' String ' , true )])
-> setArguments ([ ' name ' => ' $name ' ])
-> setSelectionSet (
[
' id ' ,
' number ' ,
' name ' ,
( new Query ( ' evolutions ' ))
-> setSelectionSet (
[
' id ' ,
' number ' ,
' name ' ,
( new Query ( ' attacks ' ))
-> setSelectionSet (
[
( new Query ( ' fast ' ))
-> setSelectionSet (
[
' name ' ,
' type ' ,
' damage ' ,
]
)
]
)
]
)
]
);
try {
$ name = readline ( ' Enter pokemon name: ' );
$ results = $ client -> runQuery ( $ gql , true , [ ' name ' => $ name ]);
}
catch ( QueryError $ exception ) {
print_r ( $ exception -> getErrorDetails ());
exit ;
}
print_r ( $ results -> getData ()[ ' pokemon ' ]);
أو بدلاً من ذلك، هذه هي الطريقة التي يمكن بها إنشاء هذا الاستعلام باستخدام فئة QueryBuilder:
$ client = new Client (
' https://graphql-pokemon.now.sh/ '
);
$ builder = ( new QueryBuilder ( ' pokemon ' ))
-> setVariable ( ' name ' , ' String ' , true )
-> setArgument ( ' name ' , ' $name ' )
-> selectField ( ' id ' )
-> selectField ( ' number ' )
-> selectField ( ' name ' )
-> selectField (
( new QueryBuilder ( ' evolutions ' ))
-> selectField ( ' id ' )
-> selectField ( ' name ' )
-> selectField ( ' number ' )
-> selectField (
( new QueryBuilder ( ' attacks ' ))
-> selectField (
( new QueryBuilder ( ' fast ' ))
-> selectField ( ' name ' )
-> selectField ( ' type ' )
-> selectField ( ' damage ' )
)
)
);
try {
$ name = readline ( ' Enter pokemon name: ' );
$ results = $ client -> runQuery ( $ builder , true , [ ' name ' => $ name ]);
}
catch ( QueryError $ exception ) {
print_r ( $ exception -> getErrorDetails ());
exit ;
}
print_r ( $ results -> getData ()[ ' pokemon ' ]);
على الرغم من أنه ليس الهدف الأساسي لهذه الحزمة، إلا أنها تدعم تشغيل استعلامات السلسلة الأولية، تمامًا مثل أي عميل آخر يستخدم طريقة runRawQuery
في فئة Client
. فيما يلي مثال على كيفية استخدامه:
$ gql = <<<QUERY
query {
pokemon(name: "Pikachu") {
id
number
name
attacks {
special {
name
type
damage
}
}
}
}
QUERY ;
$ results = $ client -> runRawQuery ( $ gql );