Membangun Server GraphQL Menggunakan Laravel - CRUDPRO

Membangun Server GraphQL Menggunakan Laravel

GraphQL adalah bahasa query API yang dapat digunakan untuk meminta data dari server sambil memungkinkan klien untuk menentukan dengan tepat data apa yang mereka butuhkan. Pengembang lepas Toptal Christopher Moore menjelaskan cara menggunakan Laravel Framework untuk membuat server GraphQL dan memberikan beberapa contoh query hubungan, mutasi, otentikasi, dan banyak lagi.

Jika Anda baru mengenal GraphQL, GraphQL adalah bahasa query yang digunakan untuk berinteraksi dengan API dan memiliki beberapa keunggulan dibandingkan arsitektur alternatif seperti REST. GraphQL sangat berguna ketika digunakan sebagai titik akhir untuk aplikasi seluler dan halaman tunggal. GraphQL membuatnya relatif mudah untuk menanyakan data terkait bersarang dalam sebuah permintaan, memberikan pengembang data yang tepat yang mereka butuhkan dalam satu perjalanan pulang pergi ke server.

Laravel adalah framework web PHP yang populer dan kontroversial. Ini menyediakan sejumlah alat bawaan untuk meluncurkan dan menjalankan aplikasi Anda dengan cepat, tetapi pengembang juga dapat mengganti implementasi mereka sendiri dengan antarmuka bawaan Laravel jika diinginkan.

Komunitas di sekitar GraphQL dan Laravel telah berkembang secara dramatis sejak open source, tetapi masih ada sedikit dokumentasi tentang cara menggunakan kedua teknologi ini bersama-sama.

Oleh karena itu, tutorial ini akan menunjukkan kepada Anda bagaimana menggunakan Laravel untuk membuat server GraphQL Anda sendiri.

Ulasan Project

Sebelum memulai, Anda harus terbiasa dengan proyek yang ingin Anda bangun. Untuk melakukannya, tentukan sumber daya Anda dan buat skema GraphQL. Skema ini akan digunakan nanti untuk menyediakan API.

Sumber daya project

Aplikasi kami terdiri dari dua sumber: Article dan User. Sumber daya ini didefinisikan sebagai tipe objek dalam skema GraphQL.

type Query {
user(id: ID!): User
  users: [User!]!

  article(id: ID!): Article
  articles: [Article!]!
}

Melihat skema, kita dapat melihat bahwa ada hubungan one-to-many antara dua objek. user dapat menulis banyak Article, dan artikel ditugaskan penulis (user).

Sekarang setelah kita mendefinisikan tipe objek, kita memerlukan cara untuk membuat dan mengkueri data, jadi mari kita definisikan objek kueri dan objek mutasi.


type Query {
user(id: ID!): User
  users: [User!]!

  article(id: ID!): Article
  articles: [Article!]!
}
type Mutation {
  createUser(name: String!, email: String!, password: String!): User
  createArticle(title: String!, content: String!): Article
}

Pengaturan project Laravel

Sekarang kita telah mendefinisikan skema GraphQL, mari kita jalankan proyek Laravel. Mari kita mulai dengan membuat Laravel baru melalui proyek Composer:

$ composer create-project --prefer-dist laravel/laravel laravel-graphql

Untuk memastikan semuanya berfungsi, mulai server dan pastikan Anda berada di halaman default Laravel.

$ cd laravel-graphql
$ php artisan serve
Laravel development server started: <http://127.0.0.1:8000>

Model dan Migrasi Basis Data

Untuk keperluan artikel ini, kita akan menggunakan SQLite. Jadi, mari buat perubahan berikut pada file .env default:

DB_CONNECTION=sqlite
# DB_HOST=
# DB_PORT=
# DB_DATABASE=database.sqlite
# DB_USERNAME=
# DB_PASSWORD=

Selanjutnya, mari kita buat file database:

$ touch ./database/database.sqlite

Laravel hadir dengan users model dan beberapa file migrasi dasar. Mari dengan cepat menambahkan kolom api_token di file migrasi CreateUsersTable yang disediakan oleh Laravel.

// /database/migrations/XXXX_XX_XX_000000_create_users_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->string('api_token', 80)->unique()->nullable()->default(null);
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

Setelah disetujui, kami akan kembali ke kolom tambahan ini nanti di Article ini. Selanjutnya, mari buat model Article dan file migrasi untuk membuat tabel yang relevan.

$ php artisan make:model Article -m

Catatan: Opsi -m membuat file migrasi untuk model artikel yang baru dibuat.

Mari kita membuat beberapa penyesuaian pada file migrasi yang dihasilkan.

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

class CreateArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('user_id');
            $table->string('title');
            $table->text('content');
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users');
        });
    }

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

Menambahkan ID tabel users dan foreign key yang menunjuk ke kolom title dan konten yang ditentukan dalam skema GraphQL.

Sekarang setelah file migrasi ditentukan, mari kita lanjutkan dan menjalankannya terhadap database.

$ php artisan migrate

Selanjutnya, mari kita definisikan hubungan yang diperlukan dan perbarui model.

// app/User.php
namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    // ...

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function articles()
    {
        return $this->hasMany(Article::class);
    }
}
// app/Article.php
namespace App;

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'title', 'content',
    ];

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Database Seeding

Sekarang setelah Anda menyiapkan model dan migrasi, mari siapkan seed untuk database Anda. Pertama, buat beberapa kelas seeder untuk artikel dan tabel user.

$ php artisan make:seeder UsersTableSeeder 
$ php artisan make:seeder ArticlesTableSeeder

Selanjutnya, mari kita atur untuk memasukkan data dummy ke dalam database SQLite.

// database/seeds/UsersTableSeeder.php
use App\User;
use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run()
    {
        \App\User::truncate();

        $faker = \Faker\Factory::create();
        $password = bcrypt('secret');

        \App\User::create([
            'name'     => $faker->name,
            'email'    => '[email protected]',
            'password' => $password,
        ]);

        for ($i = 0; $i < 10; ++$i) {
            \App\User::create([
                'name'     => $faker->name,
                'email'    => $faker->email,
                'password' => $password,
            ]);
        }
    }
}
database/seeds/ArticlesTableSeeder.php
use App\Article;
use Illuminate\Database\Seeder;

class ArticlesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run()
    {
        \App\Article::truncate();
        \App\Article::unguard();

        $faker = \Faker\Factory::create();

        \App\User::all()->each(function ($user) use ($faker) {
            foreach (range(1, 5) as $i) {
                \App\Article::create([
                    'user_id' => $user->id,
                    'title'   => $faker->sentence,
                    'content' => $faker->paragraphs(3, true),
                ]);
            }
        });
    }
}
// /database/seeds/DatabaseSeeder.php
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(UsersTableSeeder::class);
        $this->call(ArticlesTableSeeder::class);
    }
}

Terakhir, mari kita jalankan seeder database untuk memasukkan data ke dalam database.

$ php artisan db:seed

Laravel Lighthouse dan Server GraphQL

Sekarang Anda telah menyiapkan database dan model Anda, saatnya untuk mulai membangun server GraphQL Anda. Saat ini ada beberapa solusi yang tersedia di Laravel, tetapi artikel ini menggunakan Lighthouse.

Lighthouse adalah paket yang saya buat beberapa tahun yang lalu dan baru-baru ini mendapat dukungan luar biasa dari komunitas yang berkembang di sekitarnya. Hal ini memungkinkan pengembang untuk dengan cepat menyiapkan server GraphQL menggunakan Laravel, yang memiliki sedikit boilerplate, sambil memberikan fleksibilitas kepada pengembang untuk menyesuaikannya untuk memenuhi kebutuhan hampir semua proyek.

Mari kita mulai dengan memasukkan paket ke dalam proyek.

$ composer require nuwave/lighthouse:"3.1.*"

Selanjutnya, mari kita publikasikan file konfigurasi Lighthouse.

$ php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider" --tag=config

Catatan: Anda juga dapat mengekspos file skema default Lighthouse hanya dengan menghapus opsi -tag = config. Namun, pada artikel ini, kami akan membuat file skema dari awal.

Jika Anda melihat file config/lighthouse.php, Anda akan melihat pengaturan yang digunakan untuk mendaftarkan file skema dengan Lighthouse.

'schema' => [
    'register' => base_path('graphql/schema.graphql'),
],

Sekarang mari kita lanjutkan dan buat file skema untuk mengatur tipe objek user dan query.

$ mkdir graphql
$ touch ./graphql/schema.graphql
// /graphql/schema.graphql
type User {
  id: ID!
  name: String!
  email: String!
}

type Query {
  user(id: ID! @eq): User @find
  users: [User!]! @all
}

Anda akan melihat bahwa skema mirip dengan yang didefinisikan sebelumnya, kecuali bahwa kami telah menambahkan beberapa pengidentifikasi yang disebut arahan skema.

Mari kita menguraikan skema yang ditentukan. Definisi pertama adalah tipe objek yang disebut user, yang terkait dengan model fasih dari App\user. Saya telah mendefinisikan ID, nama, dan alamat email sebagai field yang dapat ditanyakan dari model users. Atau, ini berarti kolom password, create_at, dan updated_at adalah field yang tidak dapat ditanyakan oleh API.

Selanjutnya, terdapat tipe query yang merupakan entry point ke API dan dapat digunakan untuk query data. field pertama adalah field user, yang mengembalikan larik tipe objek user. Arahan @all memberi tahu Lighthouse untuk mengeksekusi query Eloquent menggunakan model user dan mendapatkan semua hasilnya. Ini sama dengan melakukan hal berikut:

$users = \App\User::all();

Catatan: Lighthouse tahu untuk mencari model di \App\User namespace karena memiliki opsi namespace yang ditentukan dalam file konfigurasi.

field kedua yang ditentukan dalam jenis query adalah calluser. Dibutuhkan id sebagai argumen dan mengembalikan tipe objek user tunggal. Kami juga telah menambahkan dua arahan untuk membantu Lighthouse secara otomatis membuat query dan mengembalikan model user tunggal. Arahan @eq memberi tahu Lighthouse untuk menambahkan tempat ke kolom id, dan arahan @find memberi tahu Lighthouse untuk mengembalikan satu hasil. Untuk membuat query ini menggunakan Pembuat query Laravel:

$user = \App\User::where('id', $args['id'])->first();

Permintaan GraphQL API

Sekarang kita memiliki beberapa wawasan tentang bagaimana Lighthouse menggunakan skema untuk membuat query, mari jalankan server dan mulai query data. Mulailah dengan menjalankan server.

$ php artisan serve
Laravel development server started: <http://127.0.0.1:8000>

Untuk menanyakan titik akhir GraphQL, Anda dapat menjalankan perintah cURL di terminal atau klien standar seperti Postman. Namun, untuk mendapatkan semua manfaat GraphQL (pelengkapan otomatis, penyorotan kesalahan, dokumentasi, dll.), gunakan GraphQL Playground (rilis unduhan di sini).

Untuk meluncurkan Playground, klik tab URL Endpoints dan masukkan http://localhost:8000/graphql untuk mengarahkan GraphQL Playground ke server Anda. Anda dapat menanyakan data di sisi kiri editor, jadi mari kita mulai dengan menanyakan semua user yang diunggulkan dalam database.

{
  users {
    id
    email
    name
  }
}

Tekan tombol putar di tengah IDE (atau klik Ctrl + Enter) dan Anda akan melihat output JSON server di sebelah kanan. Ini terlihat seperti ini:

{
  "data": {
    "users": [
      {
        "id": "1",
        "email": "[email protected]",
        "name": "Carolyn Powlowski"
      },
      {
        "id": "2",
        "email": "[email protected]",
        "name": "Elouise Raynor"
      },
      {
        "id": "3",
        "email": "[email protected]",
        "name": "Mrs. Dejah Wiza"
      },
      ...
    ]
  }
}

Catatan: Karena kami menggunakan Faker untuk menyemai basis data, data di field surat dan nama berbeda.

Sekarang mari kita coba permintaan user tunggal

{
  user(id: 1) {
    email
    name
  }
}

Anda juga akan mendapatkan output berikut untuk satu user:

{
  "data": {
    "user": {
      "email": "[email protected]",
      "name": "Carolyn Powlowski"
    }
  }
}

Ada baiknya untuk mulai membuat query untuk data seperti itu, tetapi sangat kecil kemungkinannya Anda akan berada dalam proyek di mana Anda ingin menanyakan semua data, jadi mari tambahkan pagination. Jika Anda melihat berbagai built-in directive di Lighthouse, directive @paginate langsung tersedia, jadi mari kita update objek query dalam skema sebagai berikut:

type Query {
  user(id: ID! @eq): User @find
  users: [User!]! @paginate
}

Apa yang terjadi ketika saya memuat ulang GraphQL Playground (Ctrl / Cmd + R) dan mencoba query user lagi dengan pesan kesalahan yang menyatakan bahwa field "id" tipe "UserPaginator" tidak dapat ditanyakan? Di balik layar, Lighthouse memanipulasi skema untuk mendapatkan serangkaian hasil yang diberi halaman dan mengubah tipe pengembalian di field user.

Mari kita lihat lebih dekat skema di tab Dokumen GraphQL Playground. Melihat field user, kami mengembalikan UserPaginator yang mengembalikan larik user dan tipe PaginatorInfo yang ditentukan di Lighthouse.

type UserPaginator {
  paginatorInfo: PaginatorInfo!
  data: [User!]!
}

type PaginatorInfo {
  count: Int!
  currentPage: Int!
  firstItem: Int
  hasMorePages: Boolean!
  lastItem: Int
  lastPage: Int!
  perPage: Int!
  total: Int!
}

Jika Anda terbiasa dengan pagination bawaan Laravel, field yang tersedia untuk tipe PaginatorInfo mungkin akan sangat familiar. Jadi, untuk menanyakan dua user, dapatkan jumlah total user dalam sistem, dan lihat bahwa masih ada halaman yang beredar, kirim query berikut:

{
  users(count:2) {
    paginatorInfo {
      total
      hasMorePages
    }
    data {
      id
      name
      email
    }
  }
}

Ini akan memberi Anda respons berikut:

{
  "data": {
    "users": {
      "paginatorInfo": {
        "total": 11,
        "hasMorePages": true
      },
      "data": [
        {
          "id": "1",
          "name": "Carolyn Powlowski",
          "email": "[email protected]"
        },
        {
          "id": "2",
          "name": "Elouise Raynor",
          "email": "[email protected]"
        },
      ]
    }
  }
}

Relationships

Secara umum, banyak data yang relevan saat mengembangkan aplikasi. Dalam hal ini, user dapat menulis banyak artikel, jadi mari tambahkan hubungan itu ke tipe user dan tentukan tipe artikelnya.


type User {
  id: ID!
  name: String!
  email: String!
  articles: [Article!]! @hasMany
}

type Article {
  id: ID!
  title: String!
  content: String!
}

Di sini kita menggunakan arahan skema lain @hasMany yang disediakan oleh Lighthouse. Ini memberitahu Lighthouse bahwa model user memiliki hubungan \Illuminate\Database\Eloquent\Relationships\HasMany dengan model Article.

Selanjutnya, mari kita query hubungan yang baru didefinisikan.

{
  user(id:1) {
    articles {
      id
      title
    }
  }
}

Ini akan mengembalikan respons berikut:

{
  "data": {
    "user": {
      "articles": [
        {
          "id": "1",
          "title": "Aut velit et temporibus ut et tempora sint."
        },
        {
          "id": "2",
          "title": "Voluptatem sed labore ea voluptas."
        },
        {
          "id": "3",
          "title": "Beatae sit et maxime consequatur et natus totam."
        },
        {
          "id": "4",
          "title": "Corrupti beatae cumque accusamus."
        },
        {
          "id": "5",
          "title": "Aperiam quidem sit esse rem sed cupiditate."
        }
      ]
    }
  }
}

Terakhir, mari kita balikkan hubungan dan gunakan arahan skema @belongsTo Lighthouse untuk memperbarui query dan menambahkan hubungan penulis ke tipe objek Artikel.

type Article {
  id: ID!
  title: String!
  content: String!
  author: User! @belongsTo(relation: "user")
}

type Query {
  user(id: ID! @eq): User @find
  users: [User!]! @paginate
  article(id: ID! @eq): Article @find
  articles: [Article!]! @paginate
}

Anda dapat melihat bahwa kami telah menambahkan argumen relasi opsional ke direktif @belongsTo. Ini memberitahu Lighthouse untuk menggunakan hubungan user model Artikel dan menetapkannya ke field penulis.

Kemudian query daftar artikel untuk mendapatkan penulis yang relevan.

{
  articles(count:2) {
    paginatorInfo {
      total
      hasMorePages
    }
    data {
      id
      title
      author {
        name
        email
      }
    }
  }
}

Maka Anda perlu mendapatkan yang berikut dari server:

{
  "data": {
    "articles": {
      "paginatorInfo": {
        "total": 55,
        "hasMorePages": true
      },
      "data": [
        {
          "id": "1",
          "title": "Aut velit et temporibus ut et tempora sint.",
          "author": {
            "name": "Carolyn Powlowski",
            "email": "[email protected]"
          }
        },
        {
          "id": "2",
          "title": "Voluptatem sed labore ea voluptas.",
          "author": {
            "name": "Carolyn Powlowski",
            "email": "[email protected]"
          }
        }
      ]
    }
  }
}

GraphQL Mutation

Sekarang setelah Anda dapat mengquery data Anda, mari buat beberapa mutasi untuk membuat user dan artikel baru. Mari kita mulai dengan model user.

type Mutation {
  createUser(
    name: String!
    email: String! @rules(apply: ["email", "unique:users"])
    password: String! @bcrypt @rules(apply: ["min:6"])
  ): User @create
}

Sekarang mari kita urai definisi skema ini. Saya membuat mutasi bernama createUser. Mutasi ini membutuhkan tiga argumen (nama, alamat email, kata sandi). Saya menerapkan arahan @rules ke argumen email dan kata sandi. Ini mungkin sedikit familiar karena mirip dengan logika validasi yang disediakan Laravel ke controller.

Kemudian saya melampirkan arahan @bcrypt ke field kata sandi. Ini memastikan bahwa kata sandi dienkripsi sebelum diteruskan ke model yang baru dibuat.

Terakhir, untuk membantu membuat model baru, Lighthouse menyediakan arahan skema @create yang mengambil argumen yang ditentukan dan membuat model baru. Menjalankan logika yang sama pada pengontrol akan terlihat seperti ini:

use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Create a new user.
     *
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $data = $this->validate($request, [
            'email' => ['email', 'unique:users'],
            'password' => ['min:6']
        ]);

        $user = \App\User::create($data);

        return response()->json(['user' => $user]);
    }
}

Sekarang field mutasi createUser telah disetel, lanjutkan dan jalankan di GraphQL Playground sebagai berikut:

mutation {
  createUser(
    name:"John Doe"
    email:"[email protected]"
    password: "secret"
  ) {
    id
    name
    email
  }
}
Anda harus mendapatkan output berikut:
{
  "data": {
    "createUser": {
      "id": "12",
      "name": "John Doe",
      "email": "[email protected]"
    }
  }
}

Otentikasi dan Otorisasi GraphQL

Ini adalah kesempatan bagus untuk memverifikasi otentikasi dan otorisasi di GraphQL/Lighthouse karena kami perlu menambahkan user_id ke model Article.

Untuk mengautentikasi user, kita perlu menyediakan api_token kepada user, jadi buat mutasi untuk menanganinya dan tambahkan @field directive yang menunjuk ke Lighthouse sebuah resolver khusus untuk menangani logika. Setel resolver dalam pola yang sama dengan yang Anda definisikan pengontrol di Laravel menggunakan argumen resolver.

Gunakan arahan @field yang ditentukan di bawah ini untuk memberi tahu Lighthouse ketika mutasi login dilakukan. Gunakan metode createToken di kelas App\GraphQL\Mutations\AuthMutator.

type Mutation {
  # ...

  login(
    email: String! 
    password: String!
  ): String @field(resolver: "AuthMutator@resolve")
}

Catatan: Tidak perlu menyertakan seluruh namespace di sini. Anda dapat melihat di file konfigurasi lighthouse.php bahwa namespace yang ditentukan untuk mutasi sudah ditetapkan sebagai App\\GraphQL\\Mutations, tetapi Anda dapat menggunakan namespace lengkap jika Anda mau.

Buat kelas mutator baru menggunakan generator Lighthouse:
$ php artisan lighthouse:mutation AuthMutator
Selanjutnya mari kita update fungsi resolver sebagai berikut:
namespace App\GraphQL\Mutations;

use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;
use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class AuthMutator
{
    /**
     * Return a value for the field.
     *
     * @param  null  $rootValue Usually contains the result returned from the parent field. In this case, it is always `null`.
     * @param  mixed[]  $args The arguments that were passed into the field.
     * @param  \Nuwave\Lighthouse\Support\Contracts\GraphQLContext  $context Arbitrary data that is shared between all fields of a single query.
     * @param  \GraphQL\Type\Definition\ResolveInfo  $resolveInfo Information about the query itself, such as the execution state, the field name, path to the field from the root, and more.
     * @return mixed
     */
    public function resolve($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
    {
        $credentials = Arr::only($args, ['email', 'password']);

        if (Auth::once($credentials)) {
            $token = Str::random(60);

            $user = auth()->user();
            $user->api_token = $token;
            $user->save();

            return $token;
        }

        return null;
    }
}

Sekarang resolver telah disiapkan, mari kita uji dan gunakan mutasi berikut di GraphQL Playground untuk mendapatkan token API.

mutation {
  login(email:"[email protected]", password:"secret")
}

Anda perlu mengembalikan token sebagai berikut:

{
  "data": {
    "login": "VJCz1DCpmdvB9WatqvWbXBP2RN8geZQlrQatUnWIBJCdbAyTl3UsdOuio3VE"
  }
}

Catatan: Pastikan untuk menyalin token yang dikembalikan oleh mutasi login untuk digunakan nanti.

Kemudian tambahkan field query yang mengembalikan user yang diautentikasi untuk memverifikasi bahwa logika berfungsi. Tambahkan field yang disebut me dan gunakan arahan @auth Lighthouse untuk mengembalikan user yang saat ini diautentikasi. Juga, atur argumen guard ke api. Ini adalah cara untuk mengautentikasi user.

type Query {
  # ...
  me: User @auth(guard: "api")
}

Sekarang mari kita jalankan querynya. Di GraphQL Playground, Anda dapat mengatur header permintaan dengan mengklik dua kali tab HttpHeaders di bagian bawah. Untuk menambahkan token pembawa ke setiap permintaan untuk menambahkan header menggunakan objek JSON, tambahkan:

{
  "Authorization": "Bearer VJCz1DCpmdvB9WatqvWbXBP2RN8geZQlrQatUnWIBJCdbAyTl3UsdOuio3VE"
}

Catatan: Ganti token pembawa dengan token yang Anda terima saat menjalankan query login.

Sekarang mari kita jalankan query me.

{
  me {
    email
    articles {
      id
      title
    }
  }
}
Anda harus mendapatkan output yang mirip dengan berikut ini:
{
  "data": {
    "me": {
      "email": "[email protected]",
      "articles": [
        {
          "id": "1",
          "title": "Rerum perspiciatis et quos occaecati exercitationem."
        },
        {
          "id": "2",
          "title": "Placeat quia cumque laudantium optio voluptatem sed qui."
        },
        {
          "id": "3",
          "title": "Optio voluptatem et itaque sit animi."
        },
        {
          "id": "4",
          "title": "Excepturi in ad qui dolor ad perspiciatis adipisci."
        },
        {
          "id": "5",
          "title": "Qui nemo blanditiis sed fugit consequatur."
        }
      ]
    }
  }
}

Middleware

Sekarang kita tahu bahwa otentikasi berfungsi dengan baik, mari buat mutasi terakhir dan buat artikel menggunakan user yang saat ini diautentikasi. Gunakan arahan @field untuk mengarahkan Lighthouse ke resolver dan sertakan arahan @middleware untuk memastikan bahwa user dapat masuk.

type Mutation {
  # ...

  createArticle(title: String!, content: String!): Article 
    @field(resolver: "ArticleMutator@create")
    @middleware(checks: ["auth:api"])
}
Pertama, mari kita buat kelas mutasi.
$ php artisan lighthouse:mutation ArticleMutator
Selanjutnya, mari kita perbarui mutator dengan logika berikut.
namespace App\GraphQL\Mutations;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class ArticleMutator
{
    /**
     * Return a value for the field.
     *
     * @param  null  $rootValue
     * @param  mixed[]  $args
     * @param  \Nuwave\Lighthouse\Support\Contracts\GraphQLContext  $context 
     * @return mixed
     */
    public function create($rootValue, array $args, GraphQLContext $context)
    {
        $article = new \App\Article($args);
        $context->user()->articles()->save($article);

        return $article;
    }
}

Catatan: Mengganti nama fungsi resolusi default untuk membuat. Tidak perlu membuat kelas baru untuk setiap resolver. Sebaliknya, Anda dapat mengelompokkan logika jika lebih masuk akal.

Terakhir, mari kita jalankan mutasi baru dan lihat hasilnya. Pastikan untuk menyimpan header Otorisasi query sebelum tab HTTP Header.

mutation {
  createArticle(
    title:"Building a GraphQL Server with Laravel"
    content:"In case you're not currently familiar with it, GraphQL is a query language used to interact with your API..."
  ) {
    id
    author {
      id
      email
    }
  }
}
Anda harus mendapatkan output berikut:
{
  "data": {
    "createArticle": {
      "id": "56",
      "author": {
        "id": "1",
        "email": "[email protected]"
      }
    }
  }
}

Ringkasan

Singkatnya, saya menggunakan Lighthouse untuk membuat server GraphQL untuk proyek Laravel saya. Kami menggunakan beberapa arahan skema bawaan untuk membuat query dan mutasi untuk menangani otorisasi dan otentikasi.

Dengan Lighthouse Anda dapat melakukan lebih banyak lagi (seperti memungkinkan Anda membuat arahan skema kustom Anda sendiri), tetapi untuk tujuan artikel ini, tetap berpegang pada dasar-dasarnya dan gunakan server GraphQL dengan sedikit boilerplate. dan berlari.

Lain kali Anda perlu menyiapkan API untuk aplikasi seluler atau satu halaman Anda, pertimbangkan GraphQL sebagai cara untuk menanyakan data Anda.