見出し画像

「Laravel + Vue.jsではじめる 実践 GraphQL入門」の全貌を大公開します!〜GraphQL + Laravelでバックエンドを開発!(フォロー取得機能〜プロフィール編集機能)編〜

こんにちは。kzkohashi です。
FISM という会社でCTOをやっております。

今年4月に「Laravel + Vue.jsではじめる 実践 GraphQL入門」という技術書籍を出版しました。


今回は第7弾!
「GraphQL + Laravelでバックエンドを開発!(フォロー取得機能〜プロフィール編集機能)編〜」です。

✂︎ ---------------------

プロフィール取得機能

次はログイン中のアカウントの情報を取得する機能を実装します。
この機能はアカウント情報を編集する画面で、初期表示するデータを取得するために使用します。


アカウント情報取得用のQuery(クエリ)の作成

この機能はデータの取得のみを行うため、クエリを使用します。

$ touch graphql/Queries/Account.graphql
extend type Query {
    Account: Account @auth # ①
}

@auth ディレクティブを使用すると、認証済みのアカウント情報を取得できます。
アカウント情報の取得処理の実装はこれだけです。


ログイン中のアカウントのプロフィールを取得する

lighthouse が用意しているディレクティブを使うことで、非常に簡単に機能を追加することができました。
それでは今回もGraphQL Playgroundを使用して動作を確認しましょう。

{
  Account {
    twitter_id
    name
    avatar
  } 
}
{
  "data": {
    "Account": {
      "twitter_id": "foo1",
      "name": "foo",
      "avatar": null
    } 
  }
}

無事アカウント情報を取得することができました。
次はアカウント情報の編集機能を追加して、nameとavatarを変更できるようにします。



プロフィール編集機能

プロフィール情報を取得する機能ができたので、次は編集機能を追加します。

アカウント編集用のMutation(ミューテーション)の作成

まずはミューテーションから用意しましょう。

$ touch graphql/Mutations/UpdateAccount.graphql
extend type Mutation @group(middleware: ["auth:api"]) {
    UpdateAccount( # ①
         name: String @rules(apply: ["required", "string", "max:40"])
         avatar: String # ②
    ): Account @field(resolver: "UpdateProfileResolver@resolve")
}

UpdateAccount では、表示名とアバターの2種類を変更できるようにします。
avatar はStringを型に指定していますが、これは画像がbase64エンコードされた文字列でフロントから送信されてくる想定のためです。


アカウント編集用リゾルバーの作成

UpdateProfileResolver のテンプレートを生成します。

$ php artisan lighthouse:mutation UpdateProfileResolver

生成したリゾルバーで実装する内容を次に示します。

<?php

namespace App\GraphQL\Mutations;

use App\Models\Account;
use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class UpdateAccountResolver
{

    /**
     * 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 array $args The arguments that were passed into the field.
     * @param GraphQLContext|null $context Arbitrary data that is shared between all fields of a single query.
     * @param 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 = null, ResolveInfo $resolveInfo)
    {

        /** @var \App\Models\Account $account */

        $account = auth()->user();

        $updatedAccount = $this->updateAccount($account, $args);

        return $updatedAccount;
     }

     protected function updateAccount(Account $account, array $args)
     {
         $account->name = $args['name'] ?? $account->name;

         if (isset($args['avatar'])) {
             $exploded = explode(';base64,', $args['avatar']);
             $imageType = explode('image/', $exploded[0])[1]; // ①
             $imageName = str_random() . ".{$imageType}"; // ②

             \Storage::put('public/images/' . $imageName, base64_decode($exploded[1])); // ③

             $account->avatar = $imageName;
         }

             $account->save();

             return $account;
     }
}

base64エンコードされた文字列から画像の拡張子を取得し(①)、ランダムな文字列と1で取得した拡張子を 結合してファイル名を生成します(②)。
そして画像ファイルは storage/app/public/images ディレクトリ配下に格納します(③)。


publicディスクの設定

storage配下に格納した画像ファイルは、このままだとフロントエンドから参照することができません。 画像ファイルを参照できるようにするため設定をする必要があります。
Laravelでは次のartisanコマンドを実行することで、 public/storage から storage/app/public にシンボリックリンクを張ることができます。

$ php artisan storage:link

publicディスクの詳細については参考リンクを参照ください。

参考) 


プロフィールの名前を変更してみる

ここでは名前を変更できるかどうかを試してみます。 UpdateAccountミューテーションの引数に“name”を設定して、リクエストを送信します。

mutation {
 UpdateAccount (name: "bar")
  {
    name
  } 
}

プロフィールの更新に成功すると下記のレスポンスが返却されます。

{
  "data": {
    "UpdateAccount": {
      "name": "bar"
    } 
  }
}



まとめ

以上がサーバサイドの実装です!

あとはVue.jsを実装してフロントエンドからツイートをできるようにしたり、リツイート機能を追加してカスタマイズしたり、好みの内容に作り変えてみてください。

本誌では扱っていないGraphQLやライブラリの機能などもありますので、公式サイトを参照してGraphQLについての知識を深めていただければと思います。


✂︎ ---------------------

いかがでしたでしょうか?
ここまでお読みいただき、ありがとうございます!

次回も木曜日に、第3章「GraphQL + VueでSPAフロントエンドを開発!」を公開します!

引き続きご覧くださいませ。


Fin.

▼ Twitterもやってます。よければフォローもお願いします🙇🏿‍♂️

▼ FISM社についてはこちら💁🏿‍♂️​

▼ 現在Wantedlyにて開発メンバー募集中です!GraphQL + Laravel + Vue.js + Swift で開発しております👨🏿‍💻まずはお気軽にお話ししましょう🙋🏿‍♂️


この記事が気に入ったらサポートをしてみませんか?