PHP Academy · Pelajaran

Penyelesai, Mutasi dan Langganan

Dapatkan dan ubah data melalui penyelesai.

Pelajaran 3 daripada 413 langkah

Penyelesai, Mutasi dan Langganan ialah pelajaran PHP Academy percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran PHP Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus PHP Academy merangkumi sejumlah 4 pelajaran.

Penyelesai ialah Tempat Logik Berada

Skema menerangkan apa yang wujud; penyelesai menentukan bagaimana nilai setiap medan dihasilkan. Penyelesai hanyalah sesuatu yang boleh dipanggil. Mutasi ialah penyelesai yang mengubah keadaan. Langganan menstrim nilai dari semasa ke semasa. Pelajaran ini merangkumi ketiga-tiganya serta model pelaksanaan yang menghubungkannya.

Tandatangan Penyelesai

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

  • $objectValue — nilai induk yang telah diselesaikan (rootValue pada peringkat teratas).
  • $args — argumen medan.
  • $context — keadaan dikongsi bagi setiap permintaan (pengendali pangkalan data, pengguna semasa).
  • $info — metadata AST/medan (nama medan, set pemilihan, laluan).
<?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 Lalai

Jika anda tidak menyediakan resolve, penyelesai lalai graphql-php membaca nama medan daripada nilai induk: kunci tatasusunan, sifat awam atau kaedah get<Field>(). Ini bermakna anda selalunya boleh menyelesaikan seluruh jenis objek tanpa kod sokongan dengan mengembalikan tatasusunan biasa atau objek data daripada induk.

<?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 daripada Induk kepada Anak

Pelaksanaan berlaku dari atas ke bawah: penyelesai Query.user mengembalikan seorang pengguna, yang kemudiannya menjadi $objectValue untuk User.posts; hasilnya pula menjadi induk bagi setiap Post.title. Memahami aliran ini penting — di sinilah masalah N+1 muncul (akan dibincangkan dalam pelajaran seterusnya).

<?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 (Tak Segerak)

Penyelesai boleh mengembalikan nilai atau janji. graphql-php menyediakan penyesuai janji segerak; dengan penyesuai ReactPHP/Amp, penyelesaian boleh ditangguhkan dan dikumpulkan secara kelompok. Walaupun secara segerak, mengembalikan objek Deferred membolehkan pelaksana mengumpulkan kerja dan menjalankannya selepas aras penyelesaian semasa — mekanisme yang menjadi asas 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

Mutation ialah jenis akar yang dinamakan Mutation. Mengikut konvensyen, medan peringkat teratasnya dijalankan berturutan (bukan serentak) supaya kesan sampingan tersusun. Nilai input biasanya dikumpulkan dalam InputObjectType untuk tandatangan yang kemas.

<?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(),
    ],
]);

Menyambungkan Jenis Mutasi

Medan mutasi menerima objek input sebagai argumen dan mengembalikan entiti yang dicipta (supaya klien boleh membaca semula medan dalam perjalanan pergi balik yang sama). Lakukan pengesahan dan keizinan dalam penyelesai, lalu lontarkan pengecualian apabila 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']);
            },
        ],
    ],
]);

Ralat: Selamat untuk Klien berbanding Dalaman

Secara lalai, graphql-php menyembunyikan mesej pengecualian dan memaparkan Internal server error untuk mengelakkan butiran dalaman terdedah. Untuk memaparkan mesej kepada klien, laksanakan GraphQL\Error\ClientAware dan kembalikan true daripada isClientSafe(). Tambahkan kod yang boleh dibaca mesin melalui sambungan.

<?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

Jenis akar Subscription membolehkan klien menerima strim hasil apabila acara berlaku (mesej baharu, kemas kini harga). Spesifikasi GraphQL mentakrifkan semantik langganan, tetapi graphql-php melaksanakan satu operasi bagi setiap panggilan — ia sendiri tidak menjalankan pelayan soket yang berterusan. Anda perlu menyediakan pengangkutannya.

  • graphql-php menyelesaikan muatan langganan bagi setiap acara yang anda tolak.
  • Pengangkutan (WebSocket melalui Ratchet/Mercure/Pusher) menghantar acara kepada klien.

Bentuk Penyelesai Langganan

Dalam amalan, anda membahagikan langganan kepada langkah langgan (mendaftarkan minat, mengembalikan sumber acara) dan langkah selesaikan (memetakan setiap acara kepada muatan medan). Banyak susunan PHP menggabungkan graphql-php dengan Mercure atau perantara penerbitan/langganan; penyelesai di bawah menunjukkan pemetaan setiap acara yang dipertanggungjawabkan kepada 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 ialah Saluran Pengesahan dan DI Anda

Argumen penyelesai ketiga, $context, dibina sekali bagi setiap permintaan dan dihantar kepada setiap penyelesai. Inilah tempat yang sesuai untuk pengguna yang disahkan, sambungan pangkalan data dan DataLoaders anda. Memusatkan pengesahan di sini menjadikan penyelesai lebih ringkas — penyelesai hanya bertanya kepada konteks siapakah pengguna itu, bukannya mengira semula identitinya.

<?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']);
};

Semakan Ringkas

Bagaimanakah anda menjadikan mesej pengecualian kelihatan kepada klien GraphQL?

Imbas Kembali

Anda telah mempelajari teras pelaksanaan GraphQL:

  • Penyelesai menerima ($value, $args, $context, $info); penyelesai lalai membaca kunci atau pengambil daripada induk.
  • Penyelesaian mengalir daripada induk kepada anak — punca N+1.
  • Mengembalikan Deferred/janji membolehkan pengumpulan secara kelompok.
  • Mutasi ialah medan akar berjujukan yang menggunakan InputObjectType; lakukan pengesahan/keizinan dalam penyelesai.
  • Langganan menentukan penyelesaian muatan, manakala anda menyediakan pengangkutannya.
  • ClientAware mengawal mesej ralat yang boleh dilihat oleh klien.

Seterusnya: menghapuskan masalah N+1 dengan DataLoader.

Percuma untuk bermula

Pelajari PHP dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
49
Pelajaran
195

Soalan Lazim

Adakah pelajaran “Penyelesai, Mutasi dan Langganan” percuma?

Ya — teks penuh “Penyelesai, Mutasi dan Langganan” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus PHP Academy, tingkat taraf kepada CoddyKit PRO. Kursus PHP Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Penyelesai, Mutasi dan Langganan”?

Dapatkan dan ubah data melalui penyelesai. Anda berlatih PHP Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan PHP Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran PHP Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “Penyelesai, Mutasi dan Langganan” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran PHP Academy ini?

Ya. Setiap pelajaran PHP Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. GraphQL berbanding REST
  2. Membina Skema dengan graphql-php
  3. Penyelesai, Mutasi dan Langganan
  4. Prestasi: N+1 dan DataLoader
← Kembali ke PHP Academy