Laravel ile GraphQL Sunucusu Oluşturma

Yayınlanan: 2022-03-11

Hala aşina değilseniz, GraphQL, API'nizle etkileşim kurmak için kullanılan ve REST gibi alternatif mimarilere kıyasla bazı avantajlar sağlayan bir sorgu dilidir. GraphQL, mobil ve tek sayfalık uygulamalar için bir uç nokta olarak kullanıldığında son derece kullanışlıdır. GraphQL, bir istekteki iç içe ve ilgili verileri nispeten kolaylıkla sorgulamanıza olanak tanır ve geliştiricilerin ihtiyaç duydukları tam verileri sunucuya tek bir gidiş dönüşte elde etmelerine olanak tanır.

Laravel, popüler, fikir sahibi bir PHP web çerçevesidir. Uygulamaları hızlı bir şekilde kurmak ve çalıştırmak için çok sayıda yerleşik araç sağlar, ancak aynı zamanda geliştiricilerin tercih edildiğinde kendi uygulamalarını Laravel'in yerleşik arabirimleriyle değiştirmelerine olanak tanır.

Hem GraphQL hem de Laravel'i çevreleyen topluluklar, açık kaynaklı olduklarından beri önemli ölçüde büyümüş olsa da, bu iki teknolojinin birlikte nasıl kullanılacağını açıklayan belgeler hala biraz azdır.

Bu derste size Laravel kullanarak kendi GraphQL sunucunuzu nasıl oluşturacağınızı göstereceğim.

Projeye Genel Bakış

GraphQL sunucusuna genel bakış çizimi

Başlamadan önce, inşa etmeye çalıştığımız projeye aşina olmamız gerekecek. Bunu yapmak için kaynaklarımızı tanımlayacağız ve daha sonra API'mize hizmet etmek için kullanacağımız GraphQL şemamızı oluşturacağız.

Proje Kaynakları

Uygulamamız iki kaynaktan oluşacaktır: Makaleler ve Kullanıcılar . Bu kaynaklar, GraphQL şemamızda nesne türleri olarak tanımlanacaktır:

 type User { id: ID! name: String! email: String! articles: [Article!]! } type Article { id: ID! title: String! content: String! author: User! }

Şemaya baktığımızda, iki nesnemiz arasında bire çok ilişkimiz olduğunu görebiliriz. Kullanıcılar birçok makale yazabilir ve bir makalenin kendisine atanmış bir yazarı (kullanıcısı) vardır.

Artık nesne türlerimizi tanımladığımıza göre, verilerimizi oluşturmak ve sorgulamak için bir yola ihtiyacımız olacak, o halde sorgu ve mutasyon nesnelerimizi tanımlayalım:

 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 }

Laravel Projemizi Kurmak

GraphQL şemamızı tanımladığımıza göre, şimdi Laravel projemizi çalıştıralım. Composer projesi aracılığıyla yeni bir Laravel oluşturarak başlayalım:

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

Her şeyin çalıştığından emin olmak için sunucumuzu başlatalım ve Laravel'in varsayılan sayfasını gördüğümüzden emin olalım:

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

Veritabanı Modelleri ve Geçişler

Bu makalenin amaçları doğrultusunda SQLite kullanacağız. Öyleyse, varsayılan .env dosyasında aşağıdaki değişiklikleri yapalım:

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

Ardından veritabanı dosyamızı oluşturalım:

 $ touch ./database/database.sqlite

Laravel, bir kullanıcı modeli ve bazı temel geçiş dosyalarıyla birlikte gelir. Laravel tarafından bize sağlanan CreateUsersTable taşıma dosyamıza hızlıca bir api_token sütunu ekleyelim:

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

Yetkilendirmeye geldiğimizde makalenin ilerleyen kısımlarında bu ek sütuna geri döneceğiz. Şimdi devam edelim ve ilgili tabloyu oluşturmak için makale modelimizi ve bir geçiş dosyası oluşturalım:

 $ php artisan make:model Article -m

Not: -m seçeneği, yeni oluşturulan makale modelimiz için bir geçiş dosyası oluşturur.

Oluşturulan taşıma dosyasında bazı ayarlamalar yapalım:

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

GraphQL şemamızda tanımladığımız title ve content sütunlarının yanı sıra users tablomuzdaki id işaret eden bir yabancı anahtar ekledik.

Artık geçiş dosyalarımızı tanımladığımıza göre, devam edelim ve bunları veritabanımızda çalıştıralım:

 $ php artisan migrate

Ardından, gerekli ilişkileri tanımlayarak modellerimizi güncelleyelim:

 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); } }

Veritabanı Tohumlama

Artık modellerimizi ve geçişlerimizi ayarladığımıza göre, veritabanımızı tohumlayalım. articles ve users tablolarımız için bazı ekme sınıfları oluşturarak başlayacağız:

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

Ardından, SQLite veritabanımıza bazı yapay veriler eklemek için bunları ayarlayalım:

 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); } }

Son olarak, veri tabanımıza biraz veri almak için veri tabanı tohumlayıcılarımızı çalıştıralım:

 $ php artisan db:seed

Laravel Lighthouse ve GraphQL Sunucusu

Artık veritabanımızı ve modellerimizi oluşturduğumuza göre, GraphQL sunucumuzu oluşturmaya başlamanın zamanı geldi. Şu anda Laravel için birkaç çözüm var, ancak bu makale için Lighthouse'u kullanacağız.

Lighthouse, birkaç yıl önce oluşturduğum bir paket ve son zamanlarda çevresinde büyüyen topluluktan inanılmaz bir destek gördü. Geliştiricilerin, hemen hemen her projenin gereksinimlerine uyacak şekilde özelleştirmesine izin verecek kadar esnek olmasının yanı sıra, küçük bir ortak plaka ile Laravel kullanarak bir GraphQL sunucusunu hızlı bir şekilde kurmalarına olanak tanır.

Laravel Lighthouse ve GraphQL Server çizimi

Paketi projemize çekerek başlayalım:

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

Ardından Lighthouse'un yapılandırma dosyasını yayınlayalım:

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

Not: Ayrıca, --tag=config seçeneğini kaldırarak Lighthouse'un varsayılan şema dosyasını yayınlamayı da seçebilirsiniz. Ancak bu makalenin amaçları doğrultusunda şema dosyamızı sıfırdan oluşturacağız.

config/lighthouse.php dosyasına bir göz atarsak, şema dosyamızı Lighthouse'a kaydetmek için kullanılan bir ayarı fark edeceksiniz:

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

Öyleyse devam edelim ve şema dosyamızı oluşturalım ve kullanıcı nesne tipimizi ve sorgumuzu ayarlayalım:

 $ 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 }

Şema yönergeleri adı verilen bazı tanımlayıcılar eklememiz dışında, şemamızın daha önce tanımladığımıza benzediğini fark edeceksiniz.

Tanımlanmış şemamızı parçalamak için bir dakikanızı ayıralım. İlk tanımımız, App\User anlamlı modelimiz ile ilişkisi olan User adlı bir nesne türüdür . User modellerimizde sorgulanabilecek alanlar olarak id , name ve email tanımladık. Alternatif olarak bu, password , created_at ve updated_at sütunlarının API'mizden sorgulanamayan alanlar olduğu anlamına gelir.

Ardından, API'mize bir giriş noktası olan ve verileri sorgulamak için kullanılabilen Query türümüz var. İlk alanımız, bir dizi User nesne türü döndüren users alanıdır. @all yönergesi, Lighthouse'a User modelimizi kullanarak bir Eloquent sorgusu çalıştırmasını ve tüm sonuçları almasını söyler. Bu, aşağıdakileri çalıştırmakla aynı olacaktır:

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

Not: Lighthouse, yapılandırma dosyasında tanımlanan namespaces seçeneği nedeniyle \App\User ad alanında bir model aramayı bilir.

Sorgu tipimizde tanımlı ikinci alanımız, argüman olarak bir id alan ve tek bir User nesne tipi döndüren user çağrısıdır. Ayrıca Lighthouse'un bizim için otomatik olarak bir sorgu oluşturmasına ve tek bir User modeli döndürmesine yardımcı olmak için iki yönerge ekledik. @eq yönergesi, Lighthouse'a id sütunumuza bir yer eklemesini söyler ve @find yönergesi, Lighthouse'a tek bir sonuç döndürmesini söyler. Bu sorguyu Laravel'in sorgu oluşturucusunu kullanarak yazmak için şöyle görünür:

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

GraphQL API'mizi Sorgulama

Artık Lighthouse'un sorgu oluşturmak için şemamızı nasıl kullandığına dair biraz bilgi sahibi olduğumuza göre, sunucumuzu çalıştıralım ve verileri sorgulamaya başlayalım. Sunucumuzu çalıştırarak başlayacağız:

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

Bir GraphQL uç noktasını sorgulamak için terminalde veya Postman gibi standart bir istemcide cURL komutunu çalıştırabilirsiniz. Ancak GraphQL'in tüm avantajlarından (otomatik tamamlama, hata vurgulama, belgeleme vb.) yararlanmak için GraphQL Playground'u kullanacağız (sürüm indirmeleri buradan).

Playground'u başlatırken, “URL Endpoint” sekmesine tıklayın ve GraphQL Playground'u sunucumuza yönlendirmek için http://localhost:8000/graphql yazın. Editörün sol tarafında, verilerimizi sorgulayabiliriz, bu yüzden veritabanını tohumladığımız tüm kullanıcıları sorarak başlayalım:

 { users { id email name } }

IDE'nin ortasındaki oynat düğmesine bastığınızda (veya Ctrl+Enter 'a tıkladığınızda), sağ tarafta sunucumuzun JSON çıktısını göreceksiniz, bu şuna benzer:

 { "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" }, ... ] } }

Not: Veritabanımızı tohumlamak için Faker'ı kullandığımız için email ve name alanlarındaki veriler farklı olacaktır.

Şimdi tek bir kullanıcı için sorgulamayı deneyelim:

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

Ve tek bir kullanıcı için aşağıdaki çıktıyı alacağız:

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

Bunun gibi verileri sorgulamaya başlamak güzeldir, ancak tüm verilerinizi sorgulamak isteyeceğiniz bir projede bulunmanız pek olası değildir, bu yüzden biraz sayfalandırma eklemeye çalışalım. Lighthouse'un çok çeşitli yerleşik direktiflerine bakarken, bizim için hazır bir @paginate direktifimiz var, bu yüzden şemamızın sorgu nesnesini şu şekilde güncelleyelim:

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

GraphQL Playground'u ( Ctrl/Cmd + R ) yeniden yüklersek ve users sorgusunu tekrar denersek, Cannot query field "id" on type "UserPaginator" şeklinde bir hata mesajı aldığımızı fark edeceksiniz, peki ne oldu? Perde arkasında, Lighthouse sayfalandırılmış bir sonuç kümesi elde etmemiz için şemamızı manipüle ediyor ve bunu users alanımızın dönüş türünü değiştirerek yapıyor.

GraphQL Playground'un “Docs” sekmesindeki şemamızı inceleyerek daha yakından inceleyelim. users alanına bakarsanız, bir dizi kullanıcı ve Lighthouse tanımlı PaginatorInfo türü döndüren bir UserPaginator döndürüyor:

 type UserPaginator { paginatorInfo: PaginatorInfo! data: [User!]! } type PaginatorInfo { count: Int! currentPage: Int! firstItem: Int hasMorePages: Boolean! lastItem: Int lastPage: Int! perPage: Int! total: Int! }

Laravel'in yerleşik sayfalandırmasına aşina iseniz, PaginatorInfo türünde bulunan alanlar muhtemelen size çok tanıdık gelecektir. Bu nedenle, iki kullanıcıyı sorgulamak, sistemdeki toplam kullanıcı sayısını almak ve geçiş yapacak daha fazla sayfamız olup olmadığını kontrol etmek için aşağıdaki sorguyu göndeririz:

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

Hangi bize aşağıdaki yanıtı sağlayacaktır:

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

ilişkiler

Genellikle, bir uygulama geliştirirken verilerinizin çoğu birbiriyle ilişkilidir. Bizim durumumuzda, bir User birçok Articles yazabilir, bu yüzden bu ilişkiyi Kullanıcı türümüze ekleyelim ve Article türümüzü tanımlayalım:

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

Burada, Lighthouse'a User modelimizin Article modeliyle \Illuminate\Database\Eloquent\Relations\HasMany ilişkisi olduğunu söyleyen başka bir Lighthouse tarafından sağlanan şema yönergesi @hasMany kullanıyoruz.

Şimdi yeni tanımladığımız ilişkimizi sorgulayalım:

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

Bu bize aşağıdaki yanıtı verecektir:

 { "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." } ] } } }

Son olarak, Lighthouse'ın @belongsTo şema yönergesini kullanarak ve Sorgumuzu güncelleyerek, ilişkimizi tersine Query ve author ilişkimizi Article nesne türümüze ekleyelim:

 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 }

@belongsTo yönergesine isteğe bağlı bir relation argümanı eklediğimizi göreceksiniz. Bu, Lighthouse'a Articles modelinin user ilişkisini kullanmasını ve bunu author alanına atamasını söyler.

Şimdi bir makale listesi sorgulayalım ve ilgili yazarlarını alalım:

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

Ve sunucumuzdan aşağıdakileri almalıyız:

 { "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 Mutasyonu

Artık verilerimizi sorgulayabileceğimize göre, bazı yeni kullanıcılar ve makaleler oluşturmak için bazı mutasyonlar oluşturalım. Kullanıcı modelimiz ile başlayacağız:

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

Şimdi bu şema tanımını parçalayalım. Üç bağımsız değişken ( name , email ve password ) alan createUser adında bir mutasyon yarattık. @rules yönergesini hem email hem de password argümanlarımıza uyguladık. Bu biraz tanıdık gelebilir çünkü Laravel'in kontrolörleri için sağladığı doğrulama mantığına benzer.

Ardından, @bcrypt yönergesini password alanımıza ekledik. Bu, parolayı yeni oluşturulan modele geçmeden önce şifreleyecektir.

Son olarak, yeni modeller oluşturmamıza yardımcı olmak için Lighthouse, tanımladığımız argümanları alacak ve yeni bir model oluşturacak bir @create schema yönergesi sağlar. Aynı mantığı bir Denetleyicide gerçekleştirmek aşağıdaki gibi görünecektir:

 namespace App\Http\Controllers; 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]); } }

Artık createUser mutasyon alanımızı oluşturduğumuza göre, devam edelim ve GraphQL Playground'da aşağıdakilerle çalıştıralım:

 mutation { createUser( name:"John Doe" email:"[email protected]" password: "secret" ) { id name email } }

Aşağıdaki çıktıyı almalıyız:

 { "data": { "createUser": { "id": "12", "name": "John Doe", "email": "[email protected]" } } }

GraphQL Kimlik Doğrulama ve Yetkilendirme

Article modellerimize bir user_id eklememiz gerektiğinden, şimdi GraphQL/Lighthouse'da kimlik doğrulama ve yetkilendirmeyi gözden geçirmek için harika bir zaman olacaktır.

resim alt metni

Bir kullanıcının kimliğini doğrulamak için, onlara bir api_token sağlamamız gerekiyor, bu yüzden bunu işlemek için bir mutasyon oluşturalım ve Lighthouse'u mantığı işleyecek özel bir çözümleyiciye yönlendirmek için @field yönergesini ekleyeceğiz. Çözümleyiciyi, resolver argümanını kullanarak Laravel'de bir denetleyici tanımlamayla aynı düzende ayarladık.

Aşağıda tanımlanan @field yönergesiyle, login mutasyonu çalıştırıldığında Lighthouse'a bildiriyoruz, App\GraphQL\Mutations\AuthMutator sınıfımızda createToken yöntemini kullanın:

 type Mutation { # ... login( email: String! password: String! ): String @field(resolver: "AuthMutator@resolve") }

Not: Tüm ad alanını buraya eklemeniz gerekmez. lighthouse.php yapılandırma dosyasında, mutasyonlarımız için zaten App\\GraphQL\\Mutations olarak ayarlanmış ad alanına sahip olduğumuzu göreceksiniz - ancak isterseniz tam ad alanını kullanabilirsiniz.

Yeni mutator sınıfını oluşturmak için Lighthouse'ın oluşturucusunu kullanalım:

 $ php artisan lighthouse:mutation AuthMutator

Ardından, çözümleyici işlevimizi şu şekilde güncelleyelim:

 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; } }

Artık çözümleyicimizi kurduğumuza göre, test edelim ve GraphQL Playground'da aşağıdaki mutasyonu kullanarak bir API belirteci elde etmeye çalışalım:

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

Bize şu şekilde geri gönderilen bir jeton almalıyız:

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

Not: Daha sonra kullanabilmemiz için oturum açma mutasyonundan döndürülen belirteci kopyaladığınızdan emin olun.

Ardından, mantığımızın çalıştığından emin olmak için kimliği doğrulanmış kullanıcıyı döndürecek bir sorgu alanı ekleyelim. me adında bir alan ekleyeceğiz ve şu anda kimliği doğrulanmış kullanıcıyı döndürmek için Lighthouse'ın @auth yönergesini kullanacağız. Ayrıca, kullanıcının kimliğini bu şekilde doğrulayacağımız için guard argümanını api eşitleyeceğiz.

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

Şimdi sorguyu çalıştıralım. GraphQL Playground'da, alttaki "Http Headers" sekmesine çift tıklayarak istek başlıklarınızı ayarlayabilirsiniz. Bir JSON nesnesiyle başlıklar ekliyoruz, bu nedenle her isteğe bir taşıyıcı belirteci eklemek için aşağıdakileri eklemeniz gerekir:

 { "Authorization": "Bearer VJCz1DCpmdvB9WatqvWbXBP2RN8geZQlrQatUnWIBJCdbAyTl3UsdOuio3VE" }

Not: Taşıyıcı belirteci, oturum açma sorgusunu çalıştırırken aldığınız belirteçle değiştirin.

Şimdi me sorgusunu çalıştıralım:

 { me { email articles { id title } } }

Şuna benzeyen bir çıktı almalıyız:

 { "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." } ] } } }

ara katman yazılımı

Artık kimlik doğrulamamızın düzgün çalıştığını bildiğimize göre, şu anda kimliği doğrulanmış kullanıcıyı kullanarak bir makale oluşturmak için son mutasyonumuzu oluşturalım. Lighthouse'u çözümleyicimize yönlendirmek için @field yönergesini kullanacağız ve ayrıca bir kullanıcının oturum açtığından emin olmak için bir @middleware yönergesi ekleyeceğiz.

 type Mutation { # ... createArticle(title: String!, content: String!): Article @field(resolver: "ArticleMutator@create") @middleware(checks: ["auth:api"]) }

İlk önce bir mutasyon sınıfı oluşturalım:

 $ php artisan lighthouse:mutation ArticleMutator

Ardından, mutatörü aşağıdaki mantıkla güncelleyelim:

 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; } }

Not: Varsayılan resolve işlevini create için yeniden adlandırdık. Her çözümleyici için yeni bir sınıf oluşturmanız gerekmez. Bunun yerine, daha mantıklı geliyorsa mantığı birlikte gruplayabilirsiniz.

Son olarak yeni mutasyonumuzu çalıştıralım ve çıktıyı kontrol edelim. "HTTP Başlıkları" sekmesindeki önceki sorgumuzun Authorization başlığını sakladığınızdan emin olun:

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

Aşağıdaki çıktıyı almalıyız:

 { "data": { "createArticle": { "id": "56", "author": { "id": "1", "email": "[email protected]" } } } }

Toplama

Özetlemek gerekirse, Laravel projemiz için bir GraphQL sunucusu oluşturmak üzere Lighthouse'dan yararlandık. Bazı yerleşik şema yönergelerini kullandık, sorgular ve mutasyonlar oluşturduk ve yetkilendirme ve Kimlik Doğrulamayı ele aldık.

Lighthouse, çok daha fazlasını yapmanıza izin verir (örneğin, kendi özel şema yönergelerinizi oluşturmanıza izin vermek gibi), ancak bu makalenin amaçları doğrultusunda, temel bilgilere bağlı kaldık ve bir GraphQL sunucusunu oldukça küçük bir kalıp plakasıyla çalışır duruma getirmeyi başardık.

Bir dahaki sefere mobil veya tek sayfalık bir uygulama için bir API kurmanız gerektiğinde, verilerinizi sorgulamanın bir yolu olarak GraphQL'yi göz önünde bulundurduğunuzdan emin olun!

İlgili: Tam Kullanıcı Kimlik Doğrulaması ve Erişim Kontrolü – Bir Laravel Pasaport Eğitimi, Pt. 1