كيفية بناء واجهة GraphQL API باستخدام Laravel خطوة بخطوة

دقائق القراءة: 11
بناء واجهة GraphQL API باستخدام Laravel وPHP مع شرح عملي للمشروع

في هذا الدليل العملي سنتعلم كيفية إنشاء واجهة GraphQL API باستخدام PHP وLaravel بأسلوب واضح ومناسب للتطبيق الفعلي. قد تبدو مفاهيم مثل Docker وGraphQL معقدة في البداية، لكن عند تقسيمها إلى خطوات صغيرة تصبح أسهل بكثير مما يتوقعه معظم المطورين.

سننفذ مشروعاً تجريبياً بسيطاً لإدارة المهام داخل لعبة، بحيث يحتوي التطبيق على نموذجين رئيسيين: Quests وCategories. وفي نهاية الشرح ستكون لديك واجهة CRUD كاملة عبر GraphQL لكل نموذج.

مخطط قاعدة البيانات لمشروع GraphQL في Laravel يوضح العلاقات بين المهام والتصنيفات

المتطلبات الأساسية قبل البدء

قبل تنفيذ المشروع، تأكد من توفر الأدوات التالية على جهازك:

  • PHP 7+
  • Composer 2.0
  • Docker 20.10.6 أو أي إصدار قريب
  • Docker-Compose 1.29.1 أو أي إصدار قريب

ويُفضّل أيضاً أن تكون لديك معرفة أساسية بالمفاهيم التالية:

  • أساسيات Laravel مثل Eloquent وMigrations وMVC وRoutes
  • قواعد لغة PHP والبرمجة الكائنية OOP
  • فهم نظري لمفهوم GraphQL

ما الذي سنبنيه في هذا المشروع؟

سنطوّر تطبيقاً صغيراً يدور حول عالم الألعاب، ويتضمن كيانين فقط:

  • Category: لتصنيف المهام
  • Quest: لتمثيل المهمة نفسها

الهدف هو بناء واجهة GraphQL API تدعم:

  • جلب عنصر واحد
  • جلب قائمة عناصر
  • إضافة سجل جديد
  • تحديث سجل موجود
  • حذف سجل

تهيئة مشروع Laravel

ابدأ بإنشاء مشروع Laravel جديد عبر الأمر التالي:

composer create-project laravel/laravel quest_journal

سينشئ هذا الأمر مجلداً جديداً باسم quest_journal. بعد ذلك ننتقل إلى إعداد Laravel Sail لتشغيل المشروع عبر الحاويات.

# Move into the project
cd quest_journal

# Install and configure laravel sail
php artisan sail:install

عند سؤالك عن الخدمات التي تريد تثبيتها، يمكنك الضغط على Enter لاختيار MySQL فقط. إذا سارت العملية بشكل صحيح فستجد ملف docker-compose.yml داخل المشروع.

شغّل الحاويات باستخدام:

# Run the containers
./vendor/bin/sail up -d

# Check if the containers are running
docker ps

ولتسهيل الاستخدام اليومي، يمكنك إنشاء اسم مختصر للأمر sail داخل ملف bashrc أو zshrc:

# in ~/.zshrc or ~/.bashrc
alias sail='bash vendor/bin/sail'

بعد تشغيل المشروع، افتح localhost في المتصفح. من المفترض أن تظهر الصفحة الافتراضية الخاصة بـLaravel.

الصفحة الافتراضية لمشروع Laravel بعد التثبيت وتشغيل الحاويات

تثبيت الحزم اللازمة لـ GraphQL

نحتاج إلى تثبيت حزمتين أساسيتين: الأولى لتحسين تجربة التطوير، والثانية لبناء واجهة GraphQL.

# IDE helper for laravel, always useful to have.
sail composer require --dev barryvdh/laravel-ide-helper

# GraphQL library which we are going to use
sail composer require rebing/graphql-laravel

بعد التثبيت، انشر إعدادات الحزمة إلى ملفات المشروع:

sail artisan vendor:publish --provider="Rebing\GraphQL\GraphQLServiceProvider"

سيؤدي ذلك إلى إنشاء ملف إعدادات داخل المسار config/graphql.php، وهو الملف الذي سنسجل فيه الأنواع والاستعلامات وعمليات التعديل لاحقاً.

إنشاء الجداول والنماذج

إنشاء نموذج التصنيفات Category

أنشئ النموذج مع ملف الترحيل الخاص به:

sail artisan make:model -m Category

سيحتوي جدول التصنيفات على الحقول التالية:

  • id
  • title
  • created_at
  • updated_at

ملف الترحيل الخاص بجدول التصنيفات:

<?php
// database/migrations/yyyy_mm_dd_hhMMss_create_categories_table.php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->id();
            $table->text('title');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('categories');
    }
}

بعد ذلك نضبط النموذج نفسه، بحيث:

  • نجعل الحقل title قابلاً للتعبئة عبر المصفوفة $fillable
  • نعرّف العلاقة مع نموذج Quest
<?php
// App\Models\Category

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use HasFactory;

    protected $fillable = ['title'];

    public function quests()
    {
        return $this->hasMany(Quest::class);
    }
}

إنشاء نموذج المهام Quest

الآن أنشئ نموذج المهمة مع ملف الترحيل:

sail artisan make:model -m Quest

سيحتوي جدول المهام على:

  • id
  • title
  • description
  • reward
  • category_id
  • created_at
  • updated_at
<?php
// database/migrations/yyyy_mm_dd_hhMMss_create_quests_table.php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateQuestsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('quests', function (Blueprint $table) {
            $table->id();
            $table->text('title');
            $table->text('description');
            $table->integer('reward');
            $table->foreignId('category_id')->constrained();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('quests');
    }
}

لاحظ أننا استخدمنا foreignId() مع الحقل category_id، وهذا يتيح لـLaravel إنشاء علاقة مفتاح أجنبي تلقائياً بين جدولي categories وquests.

أما النموذج Quest فيكون كالتالي:

<?php
// App\Models\Quest

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Quest extends Model
{
    use HasFactory;

    protected $fillable = [
        'title',
        'category_id',
        'description',
        'reward'
    ];

    public function category()
    {
        return $this->belongsTo(Category::class);
    }
}

بعد تجهيز ملفات الترحيل والنماذج، طبّق التغييرات على قاعدة البيانات:

# Apply migrations
sail artisan migrate

توليد بيانات تجريبية داخل قاعدة البيانات

بدلاً من إدخال البيانات يدوياً، سنستخدم Factories لإنشاء سجلات اختبارية بسرعة.

# Create a factory class for quest model
sail artisan make:factory QuestFactory --model=Quest

# Create a factory class for category model
sail artisan make:factory CategoryFactory --model=Category

ملف QuestFactory

سننشئ بيانات المهام، مع اختيار category_id عشوائياً من التصنيفات الموجودة:

<?php
// database/factories/QuestFactory.php

namespace Database\Factories;

use App\Models\Category;
use App\Models\Quest;
use Illuminate\Database\Eloquent\Factories\Factory;

class QuestFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Quest::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        $categoryIDs = Category::all()->pluck('id')->toArray();

        return [
            'title' => $this->faker->title(),
            'description' => $this->faker->text(),
            'reward' => $this->faker->numberBetween(1, 100),
            'category_id' => $this->faker->randomElement($categoryIDs)
        ];
    }
}

ملف CategoryFactory

هذا الملف أبسط، لأننا نحتاج فقط إلى عنوان للتصنيف:

<?php
// database/factories/CategoryFactory.php

namespace Database\Factories;

use App\Models\Category;
use Illuminate\Database\Eloquent\Factories\Factory;

class CategoryFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Category::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'title' => $this->faker->title()
        ];
    }
}

تعبئة قاعدة البيانات

بدلاً من إنشاء ملفات Seeder متعددة، يمكننا استدعاء المصانع مباشرة من الملف DatabaseSeeder.php:

<?php
// database/seeders/DatabaseSeeder.php

namespace Database\Seeders;

use App\Models\Category;
use App\Models\Quest;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        Category::factory(10)->create();
        Quest::factory(10)->create();
    }
}

ثم نفذ الأمر التالي:

sail artisan db:seed

تنظيم بنية ملفات GraphQL داخل المشروع

أنشئ مجلداً جديداً باسم GraphQL داخل المجلد app، ثم أضف بداخله ثلاثة مجلدات:

  • Mutations
  • Queries
  • Types

هيكل مجلدات GraphQL داخل مشروع Laravel ويشمل Mutations وQueries وTypes

هذا التقسيم مهم لفهم طريقة عمل GraphQL:

  • Types: تمثل الكيانات التي يمكن إرجاعها من الواجهة البرمجية
  • Queries: مسؤولة عن جلب البيانات
  • Mutations: مسؤولة عن عمليات الإنشاء والتعديل والحذف

تعريف الأنواع Types في GraphQL

سننشئ نوعين:

  • CategoryType
  • QuestType

تعتمد هذه الأنواع على الحزمة rebing/graphql-laravel، وترث من الصنف Rebing\GraphQL\Support\Type.

ملف CategoryType

<?php
// app/graphql/types/CategoryType

namespace App\GraphQL\Types;

use App\Models\Category;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Type as GraphQLType;

class CategoryType extends GraphQLType
{
    protected $attributes = [
        'name' => 'Category',
        'description' => 'Collection of categories',
        'model' => Category::class
    ];

    public function fields(): array
    {
        return [
            'id' => [
                'type' => Type::nonNull(Type::int()),
                'description' => 'ID of quest'
            ],
            'title' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'Title of the quest'
            ],
            'quests' => [
                'type' => Type::listOf(GraphQL::type('Quest')),
                'description' => 'List of quests'
            ]
        ];
    }
}

يتكون هذا النوع من جزأين أساسيين:

  • attributes: تحتوي معلومات تعريفية عن النوع وربطه بالنموذج
  • fields(): تحدد الحقول التي يستطيع العميل طلبها

ملف QuestType

<?php
// app/graphql/types/QuestType

namespace App\GraphQL\Types;

use App\Models\Quest;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Type as GraphQLType;

class QuestType extends GraphQLType
{
    protected $attributes = [
        'name' => 'Quest',
        'description' => 'Collection of quests with their respective category',
        'model' => Quest::class
    ];

    public function fields(): array
    {
        return [
            'id' => [
                'type' => Type::nonNull(Type::int()),
                'description' => 'ID of quest'
            ],
            'title' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'Title of the quest'
            ],
            'description' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'Description of quest'
            ],
            'reward' => [
                'type' => Type::nonNull(Type::int()),
                'description' => 'Quest reward'
            ],
            'category' => [
                'type' => GraphQL::type('Category'),
                'description' => 'The category of the quest'
            ]
        ];
    }
}

إنشاء الاستعلامات Queries

لكل نموذج سننشئ استعلامين:

  • استعلام لإرجاع عنصر واحد
  • استعلام لإرجاع قائمة عناصر

ولتنظيم الكود، أنشئ داخل مجلد Queries مجلدين فرعيين:

  • Category
  • Quest

ثم أضف الملفات التالية:

  • QuestQuery
  • QuestsQuery
  • CategoryQuery
  • CategoriesQuery

تنظيم ملفات الاستعلامات Queries في مشروع GraphQL داخل Laravel

استعلام عنصر واحد من نوع Quest

<?php
// app/graphql/queries/quest/QuestQuery

namespace App\GraphQL\Queries\Quest;

use App\Models\Quest;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Query;

class QuestQuery extends Query
{
    protected $attributes = [
        'name' => 'quest',
    ];

    public function type(): Type
    {
        return GraphQL::type('Quest');
    }

    public function args(): array
    {
        return [
            'id' => [
                'name' => 'id',
                'type' => Type::int(),
                'rules' => ['required']
            ]
        ];
    }

    public function resolve($root, $args)
    {
        return Quest::findOrFail($args['id']);
    }
}

هذا النمط سيتكرر مع بقية الاستعلامات، حيث:

  • type() تحدد نوع البيانات المرجعة
  • args() تحدد المدخلات المطلوبة
  • resolve() تنفذ المنطق الفعلي لجلب البيانات

استعلامات القوائم والعناصر الأخرى

<?php
// app/graphql/queries/quest/QuestsQuery

namespace App\GraphQL\Queries\Quest;

use App\Models\Quest;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Query;

class QuestsQuery extends Query
{
    protected $attributes = [
        'name' => 'quests',
    ];

    public function type(): Type
    {
        return Type::listOf(GraphQL::type('Quest'));
    }

    public function resolve($root, $args)
    {
        return Quest::all();
    }
}
<?php
// app/graphql/queries/category/CategoryQuery

namespace App\GraphQL\Queries\Category;

use App\Models\Category;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Query;

class CategoryQuery extends Query
{
    protected $attributes = [
        'name' => 'category',
    ];

    public function type(): Type
    {
        return GraphQL::type('Category');
    }

    public function args(): array
    {
        return [
            'id' => [
                'name' => 'id',
                'type' => Type::int(),
                'rules' => ['required']
            ]
        ];
    }

    public function resolve($root, $args)
    {
        return Category::findOrFail($args['id']);
    }
}
<?php
// app/graphql/queries/category/CategoriesQuery

namespace App\GraphQL\Queries\Category;

use App\Models\Category;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Query;

class CategoriesQuery extends Query
{
    protected $attributes = [
        'name' => 'categories',
    ];

    public function type(): Type
    {
        return Type::listOf(GraphQL::type('Category'));
    }

    public function resolve($root, $args)
    {
        return Category::all();
    }
}

إنشاء عمليات Mutations

تمثل Mutations الأوامر التي تُغيّر البيانات. لكل نموذج سنحتاج إلى ثلاث عمليات:

  • إنشاء
  • تحديث
  • حذف

أنشئ داخل مجلد Mutations مجلدين فرعيين:

  • Category
  • Quest

ثم أضف هذه الملفات:

  • CreateCategoryMutation
  • DeleteCategoryMutation
  • UpdateCategoryMutation
  • CreateQuestMutation
  • DeleteQuestMutation
  • UpdateQuestMutation

هيكل ملفات Mutations في Laravel لبناء عمليات CRUD باستخدام GraphQL

إنشاء تصنيف جديد

<?php
// app/graphql/mutations/category/CreateCategoryMutation

namespace App\GraphQL\Mutations\Category;

use App\Models\Category;
use Rebing\GraphQL\Support\Mutation;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;

class CreateCategoryMutation extends Mutation
{
    protected $attributes = [
        'name' => 'createCategory',
        'description' => 'Creates a category'
    ];

    public function type(): Type
    {
        return GraphQL::type('Category');
    }

    public function args(): array
    {
        return [
            'title' => [
                'name' => 'title',
                'type' => Type::nonNull(Type::string()),
            ],
        ];
    }

    public function resolve($root, $args)
    {
        $category = new Category();
        $category->fill($args);
        $category->save();

        return $category;
    }
}

حذف وتحديث التصنيف

<?php
// app/graphql/mutations/category/DeleteCategoryMutation

namespace App\GraphQL\Mutations\Category;

use App\Models\Category;
use Rebing\GraphQL\Support\Mutation;
use GraphQL\Type\Definition\Type;

class DeleteCategoryMutation extends Mutation
{
    protected $attributes = [
        'name' => 'deleteCategory',
        'description' => 'deletes a category'
    ];

    public function type(): Type
    {
        return Type::boolean();
    }

    public function args(): array
    {
        return [
            'id' => [
                'name' => 'id',
                'type' => Type::int(),
                'rules' => ['required']
            ]
        ];
    }

    public function resolve($root, $args)
    {
        $category = Category::findOrFail($args['id']);
        return $category->delete() ? true : false;
    }
}
<?php
// app/graphql/mutations/category/UpdateCategoryMutation

namespace App\GraphQL\Mutations\Category;

use App\Models\Category;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Mutation;

class UpdateCategoryMutation extends Mutation
{
    protected $attributes = [
        'name' => 'updateCategory',
        'description' => 'Updates a category'
    ];

    public function type(): Type
    {
        return GraphQL::type('Category');
    }

    public function args(): array
    {
        return [
            'id' => [
                'name' => 'id',
                'type' => Type::nonNull(Type::int()),
            ],
            'title' => [
                'name' => 'title',
                'type' => Type::nonNull(Type::string()),
            ],
        ];
    }

    public function resolve($root, $args)
    {
        $category = Category::findOrFail($args['id']);
        $category->fill($args);
        $category->save();

        return $category;
    }
}

إنشاء مهمة جديدة

<?php
// app/graphql/mutations/quest/CreateQuestMutation

namespace App\GraphQL\Mutations\Quest;

use App\Models\Quest;
use Rebing\GraphQL\Support\Mutation;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;

class CreateQuestMutation extends Mutation
{
    protected $attributes = [
        'name' => 'createQuest',
        'description' => 'Creates a quest'
    ];

    public function type(): Type
    {
        return GraphQL::type('Quest');
    }

    public function args(): array
    {
        return [
            'title' => [
                'name' => 'title',
                'type' => Type::nonNull(Type::string()),
            ],
            'description' => [
                'name' => 'description',
                'type' => Type::nonNull(Type::string()),
            ],
            'reward' => [
                'name' => 'reward',
                'type' => Type::nonNull(Type::int()),
            ],
            'category_id' => [
                'name' => 'category_id',
                'type' => Type::nonNull(Type::int()),
                'rules' => ['exists:categories,id']
            ]
        ];
    }

    public function resolve($root, $args)
    {
        $quest = new Quest();
        $quest->fill($args);
        $quest->save();

        return $quest;
    }
}

حذف وتحديث المهمة

<?php
// app/graphql/mutations/quest/DeleteQuestMutation

namespace App\GraphQL\Mutations\Quest;

use App\Models\Quest;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Mutation;

class DeleteQuestMutation extends Mutation
{
    protected $attributes = [
        'name' => 'deleteQuest',
        'description' => 'Deletes a quest'
    ];

    public function type(): Type
    {
        return Type::boolean();
    }

    public function args(): array
    {
        return [
            'id' => [
                'name' => 'id',
                'type' => Type::nonNull(Type::int()),
                'rules' => ['exists:quests']
            ]
        ];
    }

    public function resolve($root, $args)
    {
        $category = Quest::findOrFail($args['id']);
        return $category->delete() ? true : false;
    }
}
<?php
// app/graphql/mutations/quest/UpdateQuestMutation

namespace App\GraphQL\Mutations\Quest;

use App\Models\Quest;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Mutation;

class UpdateQuestMutation extends Mutation
{
    protected $attributes = [
        'name' => 'updateQuest',
        'description' => 'Updates a quest'
    ];

    public function type(): Type
    {
        return GraphQL::type('Quest');
    }

    public function args(): array
    {
        return [
            'id' => [
                'name' => 'id',
                'type' => Type::nonNull(Type::int()),
            ],
            'title' => [
                'name' => 'title',
                'type' => Type::nonNull(Type::string()),
            ],
            'description' => [
                'name' => 'description',
                'type' => Type::nonNull(Type::string()),
            ],
            'reward' => [
                'name' => 'reward',
                'type' => Type::nonNull(Type::int()),
            ],
            'category_id' => [
                'name' => 'category_id',
                'type' => Type::nonNull(Type::int()),
                'rules' => ['exists:categories,id']
            ]
        ];
    }

    public function resolve($root, $args)
    {
        $quest = Quest::findOrFail($args['id']);
        $quest->fill($args);
        $quest->save();

        return $quest;
    }
}

تسجيل الأنواع والاستعلامات والعمليات في الإعدادات

بعد الانتهاء من بناء ملفات Types وQueries وMutations، نربطها جميعاً داخل ملف config/graphql.php:

<?php

return [
    // ... some code
    'schemas' => [
        'default' => [
            'query' => [
                'quest' => \App\GraphQL\Queries\Quest\QuestQuery::class,
                'quests' => \App\GraphQL\Queries\Quest\QuestsQuery::class,
                'category' => \App\GraphQL\Queries\Category\CategoryQuery::class,
                'categories' => \App\GraphQL\Queries\Category\CategoriesQuery::class,
            ],
            'mutation' => [
                'createQuest' => \App\GraphQL\Mutations\Quest\CreateQuestMutation::class,
                'updateQuest' => \App\GraphQL\Mutations\Quest\UpdateQuestMutation::class,
                'deleteQuest' => \App\GraphQL\Mutations\Quest\DeleteQuestMutation::class,
                'createCategory' => \App\GraphQL\Mutations\Category\CreateCategoryMutation::class,
                'updateCategory' => \App\GraphQL\Mutations\Category\UpdateCategoryMutation::class,
                'deleteCategory' => \App\GraphQL\Mutations\Category\DeleteCategoryMutation::class,
            ],
            'middleware' => [],
            'method' => ['get', 'post'],
        ],
    ],
    'types' => [
        'Quest' => \App\GraphQL\Types\QuestType::class,
        'Category' => \App\GraphQL\Types\CategoryType::class
    ],
    // some code
];

اختبار واجهة GraphQL عملياً

توفر لنا الحزمة واجهة تطوير جاهزة لاختبار الاستعلامات والعمليات. تأكد أولاً من أن حاويات Docker تعمل، ثم افتح الرابط:

http://localhost/graphiql

واجهة GraphiQL لاختبار استعلامات GraphQL داخل مشروع Laravel

بعد ذلك يمكنك تجربة السيناريوهات التالية:

جلب مهمة واحدة

مثال على استعلام GraphQL لجلب مهمة واحدة من قاعدة البيانات

جلب قائمة مهام

مثال على استعلام GraphQL لجلب قائمة من المهام في Laravel

إضافة مهمة جديدة

تنفيذ Mutation في GraphQL لإضافة مهمة جديدة إلى قاعدة البيانات

تحديث مهمة موجودة

مثال على تحديث سجل مهمة عبر GraphQL Mutation في Laravel

حذف مهمة من قاعدة البيانات

مثال على حذف مهمة باستخدام GraphQL Mutation في مشروع Laravel

لماذا يُعد GraphQL خياراً جيداً مع Laravel؟

عند استخدام GraphQL مع Laravel، تحصل على مرونة عالية في تحديد البيانات التي يحتاجها العميل بدقة، بدلاً من الاعتماد على نقاط نهاية متعددة كما هو الحال غالباً في REST. هذا يقلل من نقل البيانات غير الضرورية، ويمنح الواجهة الأمامية تحكماً أفضل في شكل الاستجابة.

كما أن دمج Eloquent مع GraphQL يجعل بناء العلاقات بين النماذج أكثر سلاسة، خاصة في المشاريع التي تحتوي على بنية بيانات مترابطة.

الخلاصة التقنية

بناء واجهة GraphQL API في Laravel ليس معقداً كما يبدو، خصوصاً عند استخدام حزمة rebing/graphql-laravel. الفكرة الأساسية تعتمد على ثلاثة مكونات واضحة: Types لتعريف شكل البيانات، وQueries لجلبها، وMutations لتعديلها. من الناحية التقنية، هذا الأسلوب مناسب جداً للمشاريع التي تحتاج إلى مرونة عالية في الاستهلاك من تطبيقات الويب أو الجوال، مع قابلية توسع ممتازة وتنظيم نظيف للكود.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *