0Pricing
PHP Academy · Pelajaran

Resolver, Mutasi, dan Langganan

Ambil dan ubah data melalui resolver.

Resolver, Mutasi, dan Langganan adalah pelajaran PHP Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar PHP Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus PHP Academy mencakup 4 pelajaran total.

Logika Berada di Penyelesai

Skema menjelaskan apa yang ada; penyelesai menentukan bagaimana nilai setiap bidang dihasilkan. Penyelesai hanyalah sesuatu yang dapat dipanggil. Mutasi adalah penyelesai yang mengubah keadaan. Langganan mengalirkan nilai dari waktu ke waktu. Pelajaran ini membahas ketiganya serta model eksekusi yang menghubungkan semuanya.

Tanda Tangan Penyelesai

Setiap penyelesai menerima empat argumen: ($objectValue, $args, $context, ResolveInfo $info).

  • $objectValue — nilai terpecahkan milik induk (rootValue di tingkat teratas).
  • $args — argumen bidang.
  • $context — keadaan bersama per permintaan (pegangan basis data, pengguna saat ini).
  • $info — metadata AST/bidang (nama bidang, set pilihan, jalur).
<?php
use GraphQL\Type\Definition\ResolveInfo;

$resolve = function ($objectValue, array $args, $context, ResolveInfo $info) {
    // $context['db'], $context['user'] set up per request
    return $context['db']->find($args['id']);
};

Penyelesai Bawaan

Jika Anda tidak menyediakan resolve, penyelesai bawaan graphql-php membaca nama bidang dari nilai induk: kunci larik, properti publik, atau metode get<Field>(). Artinya, Anda sering kali dapat menyelesaikan seluruh tipe objek tanpa kode penghubung dengan mengembalikan larik biasa atau objek transfer data (DTO) dari induknya.

<?php
// Parent returns this array; child fields resolve by key automatically:
$user = [
    'id' => 1,
    'name' => 'Ada',
    'email' => 'ada@example.com',
];
// 'name' field -> $user['name'] with no explicit resolver needed
var_dump($user['name']);

Penyelesai Mengalir dari Induk ke Anak

Eksekusi berlangsung dari atas ke bawah: penyelesai Query.user mengembalikan pengguna, yang kemudian menjadi $objectValue untuk User.posts, dan hasilnya menjadi induk bagi setiap Post.title. Memahami aliran ini sangat penting—tepat di sinilah masalah N+1 muncul (dibahas pada pelajaran berikutnya).

<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;

$userType = new ObjectType([
    'name' => 'User',
    'fields' => fn() => [
        'id'    => Type::id(),
        'name'  => Type::string(),
        'posts' => [
            'type' => Type::listOf(Type::string()),
            // $user is the parent value resolved by Query.user
            'resolve' => fn($user) => Posts::titlesForUser($user['id']),
        ],
    ],
]);

Mengembalikan Janji (Asinkron)

Penyelesai dapat mengembalikan nilai atau janji. graphql-php menyediakan adaptor janji sinkron; dengan adaptor ReactPHP/Amp, penyelesaian dapat ditunda dan dikelompokkan. Bahkan secara sinkron, mengembalikan objek Deferred memungkinkan pelaksana mengumpulkan pekerjaan dan menjalankannya setelah tingkat penyelesaian saat ini—mekanisme yang menjadi dasar DataLoader.

<?php
use GraphQL\Deferred;

$resolve = function ($post) use ($authorBuffer) {
    $authorBuffer->add($post['author_id']);   // queue the id
    return new Deferred(function () use ($authorBuffer, $post) {
        $authorBuffer->loadOnce();             // one batched query
        return $authorBuffer->get($post['author_id']);
    });
};

Mutasi Mengubah Keadaan

Mutasi hanyalah tipe akar bernama Mutation. Berdasarkan konvensi, bidang tingkat atasnya dijalankan secara berurutan (bukan secara paralel) agar efek samping tetap teratur. Masukan biasanya dikelompokkan ke dalam InputObjectType untuk mendapatkan tanda tangan yang rapi.

<?php
use GraphQL\Type\Definition\InputObjectType;
use GraphQL\Type\Definition\Type;

$createPostInput = new InputObjectType([
    'name' => 'CreatePostInput',
    'fields' => [
        'title' => Type::nonNull(Type::string()),
        'body'  => Type::string(),
    ],
]);

Menghubungkan Tipe Mutasi

Bidang mutasi menerima objek masukan sebagai argumen dan mengembalikan entitas yang dibuat (sehingga klien dapat membaca bidang kembali dalam satu perjalanan bolak-balik). Lakukan validasi dan otorisasi di dalam penyelesai, lalu lemparkan pengecualian jika gagal.

<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;

$mutationType = new ObjectType([
    'name' => 'Mutation',
    'fields' => [
        'createPost' => [
            'type' => $postType,
            'args' => ['input' => Type::nonNull($createPostInput)],
            'resolve' => function ($root, array $args, $context) {
                if (!$context['user']) {
                    throw new \RuntimeException('Unauthenticated');
                }
                return PostRepo::create($args['input'], $context['user']);
            },
        ],
    ],
]);

Galat: Aman bagi Klien vs Internal

Secara bawaan, graphql-php menyembunyikan pesan pengecualian dan menampilkan Internal server error untuk mencegah kebocoran informasi internal. Untuk menampilkan pesan kepada klien, implementasikan GraphQL\Error\ClientAware dan kembalikan true dari isClientSafe(). Tambahkan kode yang dapat dibaca mesin melalui extensions.

<?php
use GraphQL\Error\ClientAware;

class ValidationError extends \RuntimeException implements ClientAware {
    public function isClientSafe(): bool { return true; }
    // older versions also used getCategory(): string
}

Langganan: Konsepnya

Tipe akar langganan memungkinkan klien menerima aliran hasil saat peristiwa terjadi (pesan baru, perubahan harga). Spesifikasi GraphQL mendefinisikan semantik langganan, tetapi graphql-php menjalankan satu operasi per panggilan—pustaka ini tidak menyediakan peladen soket berumur panjang itu sendiri. Anda yang menyediakan transportasinya.

  • graphql-php menyelesaikan muatan langganan untuk setiap peristiwa yang Anda kirim.
  • Transportasi (WebSocket melalui Ratchet/Mercure/Pusher) mengirimkan peristiwa kepada klien.

Bentuk Penyelesai Langganan

Dalam praktiknya, Anda membagi langganan menjadi langkah pendaftaran (mendaftarkan minat dan mengembalikan sumber peristiwa) serta langkah penyelesaian (memetakan setiap peristiwa ke muatan bidang). Banyak tumpukan PHP memasangkan graphql-php dengan Mercure atau perantara publikasi/berlangganan; penyelesai di bawah ini menunjukkan pemetaan per peristiwa yang menjadi tanggung jawab graphql-php.

<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;

$subscriptionType = new ObjectType([
    'name' => 'Subscription',
    'fields' => [
        'messageAdded' => [
            'type' => $messageType,
            'args' => ['channelId' => Type::nonNull(Type::id())],
            // graphql-php resolves each pushed event into the payload;
            // a WebSocket/Mercure transport drives when this runs.
            'resolve' => fn($event) => $event['message'],
        ],
    ],
]);

Konteks Adalah Saluran Autentikasi dan DI Anda

Argumen penyelesai ketiga, $context, dibuat sekali per permintaan dan diteruskan ke setiap penyelesai. Tempat ini tepat untuk pengguna yang terautentikasi, koneksi basis data, dan DataLoaders Anda. Memusatkan autentikasi di sini membuat penyelesai tetap ringkas—penyelesai cukup menanyakan kepada konteks siapa penggunanya, bukan menghitungnya kembali.

<?php
require 'vendor/autoload.php';

// Built once per HTTP request, passed to executeQuery():
$context = [
    'user' => authenticate($_SERVER['HTTP_AUTHORIZATION'] ?? ''),
    'db'   => $pdo,
];

$resolve = function ($root, array $args, array $context) {
    if ($context['user'] === null) {
        throw new \RuntimeException('Unauthenticated');
    }
    return $context['db']->find($args['id']);
};

Pemeriksaan Singkat

Bagaimana Anda membuat pesan pengecualian terlihat oleh klien GraphQL?

Rangkuman

Anda telah mempelajari inti eksekusi GraphQL:

  • Penyelesai menerima ($value, $args, $context, $info); penyelesai bawaan membaca kunci/pengambil dari induk.
  • Penyelesaian mengalir dari induk ke anak—sumber masalah N+1.
  • Mengembalikan Deferred/janji memungkinkan pengelompokan.
  • Mutasi adalah bidang akar berurutan yang menggunakan InputObjectType; lakukan autentikasi/validasi di dalam penyelesai.
  • Langganan menentukan penyelesaian muatan, sementara Anda menyediakan transportasinya.
  • ClientAware mengendalikan pesan galat mana yang dapat dilihat klien.

Berikutnya: menuntaskan masalah N+1 dengan DataLoader.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Resolver, Mutasi, dan Langganan” gratis?

Ya — teks lengkap “Resolver, Mutasi, dan Langganan” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus PHP Academy, upgrade ke CoddyKit PRO. Kursus PHP Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Resolver, Mutasi, dan Langganan”?

Ambil dan ubah data melalui resolver. Kamu berlatih PHP Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai PHP Academy?

Tidak diperlukan pengalaman sebelumnya. PHP Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.

Berapa lama pelajaran “Resolver, Mutasi, dan Langganan” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran PHP Academy ini?

Ya. Setiap pelajaran PHP Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. GraphQL vs REST
  2. Membangun Skema dengan graphql-php
  3. Resolver, Mutasi, dan Langganan
  4. Kinerja: N+1 dan DataLoader
← Kembali ke PHP Academy