6
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Drupal】QiitaのRSSをAPI化?キャッシュ機構も組み込みました

Last updated at Posted at 2024-06-28

はじめに

この記事は前回の記事の続編です。

今回はQiitaのRSSを題材に、Drupalの Controller・API配信・キャッシュ機構 について実装を行います。

Drupalには、Routing機構 / HTTP通信 / キャッシュシステム が標準で組み込まれてます。
なので比較的やりやすいかと思います。

※ RSSがわざわざ提供されているのになんでAPI化するの? 前回の記事でも書いていますが、実務だったらこんなことしません。

用途は人それぞれですが、「毎朝Slack通知したい」「フロントエンドフレームワークを使ったPFに使いたい」「独自のAPIを用意して、複数のアプリで使いまわしたい」とか、まぁAPI化すれば色んな場面で役立ちそうですよね。自分の好きなフォーマットで実装できるっていう強みもあります。

なにやるの?

Qiitaが提供しているRSSフィードを解析して自前のAPIを配信します。

それだけだとおもしろくないので、以下の要件を加えてみます。

  1. QiitaAccountを指定できるようにする
  2. キャッシュの組み込みを行って都度HTTP通信が発生しないようにする

どうですか?ちょっとやり応えありそうな要件ですよね。

準備

■ Drupal環境の用意

環境構築はこちらを参考に。

■ Drushの導入

composer require drush/drush

Drupal開発を普段から行っている方には説明不要ですね。
Drupalの開発で大活躍のCLIツールです。

■ 再現環境

多分Drupal10x系であれば動くような書き方をしてるので、問題ないかと思いますが一応。

Drupal 10.2.7

Drush 12.4

実装はじめます

001. モジュールのセットアップ

さっそく、モジュールを実装します。とは言ってもDrushが勝手に作ってくれます。

Drush が Module作ってくれるよ😳
drush generate controller

コマンドを実行後、いろいろ聞かれるので答えてください。

わかんなかったらとりあえず Enter でいいよ
$ drush generate controller

 Welcome to controller generator!
––––––––––––––––––––––––––––––––––
 Module machine name:
 ➤ qiita
 Module name [Qiita]:
 ➤ 
 Class [QiitaController]:
 ➤ 
 Would you like to inject dependencies? [No]:
 ➤ 
 Would you like to create a route for this controller? [Yes]:
 ➤ 
 Route name [qiita.example]:
 ➤ 
 Route path [/qiita/example]:
 ➤ /api/qiita/{id}
 Route title [Example]:
 ➤ 
 Route permission [access content]:
 ➤ 

いくつかの質問に答えると、Controller付きのModuleが用意されますので有効化してしまいましょう。

Moduleの有効化
drush en qiita

002. Routing設定

Routingの設定を行います。
とは言っても、ほとんどなにもすることありません。

URLや、権限周り特にこだわりがないのであれば以下の感じでいいかと思います。

qiita.routing.yml
qiita.example:
  path: '/api/qiita/{id}'
  defaults:
    _controller: '\Drupal\qiita\Controller\QiitaController'
  requirements:
    access: TRUE

{id}がポイントですね。Controllerがアカウント名を受け取れるようにできます。

003. Controllerの実装

src/Controller/QiitaController.php
final class QiitaController extends ControllerBase {

  private const ACCOUNT_NAME = 'umekikazuya';

  /**
   * QiitaのFeedを取得しJSONを返すResponse Method.
   *   
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   *   Jsonを返すよ. 処理が上手く以下なかったら 403 を返すよ.
   */
  public function __invoke(): JsonResponse {
    $res = new JsonResponse();

    // URLを設定.
    $url = 'https://qiita.com/' . self::ACCOUNT_NAME . '/feed';
    try {
      // HTTP通信実行.
      $http_request = $this->httpClient->get($url);
      $feed = $http_request->getBody()->getContents();
      if (!$feed) {
        throw new \Exception();
      }
      // 取得情報をXMLデータに変換. (Private関数は前回の記事を見てね)
      $data = $this->loadRawFeedData($feed);
      if (!$data) {
        throw new \Exception();
      }
      // XMLデータを好みのフォーマットに変換. (Private関数は前回の記事を見てね)
      $data = $this->parseXml($data, $rss_url);
      // JSONに変換してAPIを提供!!.
      return $res->setJson(json_encode($data));
    }
    catch (\Exception $e) {
      // 失敗してたら 403 返すよ.
      return $res->setStatusCode(403);
    }
  }

}

前回の記事で、取得データのXML変換・XMLパースについて触れていますのでそちらもぜひ。

004. ちょっと休憩(一旦動作確認)

ひとまずお疲れ様です。この時点でAPIの実装は完了です。

アクセスしてみてください。

{HOST URL}/api/qiita/umekikazuya

JSON返ってきましたか?

005. URLに応じてアカウントごとのデータ取得を取得

今はどんなURLを投げても同じJSONが返ってくるはずです。

どのURLでも結果は同じはず
{HOST URL}/api/qiita/umekikazuya
{HOST URL}/api/qiita/hogehoge
{HOST URL}/api/qiita/fugafuga

Routing設定で/api/qiita/{id}と指定しているので、アカウント名を受け取るよう実装を修正します。

QiitaController.php
final class QiitaController extends ControllerBase {

-   private const ACCOUNT_NAME = 'umekikazuya';

  /**
   * QiitaのFeedを取得しJSONを返すResponse Method.
   * 
+    * @param string $id
+    *   Qiita accout id.
+    *   
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   *   Jsonを返すよ. 処理が上手く以下なかったら 403 を返すよ.
   */
-  public function __invoke(): JsonResponse {
+  public function __invoke(string $id): JsonResponse {
    $res = new JsonResponse();

-     // URLを設定.
+     // ここでアカウント別のHTTPリクエストを行うよ.
    $url = 'https://qiita.com/' . id . '/feed';

    /** 省略 */
    
  }

}

実装はこれだけです。

{id} を指定したエンドポイントでアクセスしてみてください。

006. キャッシュの組み込み

このままだと、正直RSS配信されてるのにAPIを提供するって正直意味ないですよね。
キャッシュを効かせます。アカウントごとに。

Drupalのキャッシュはすごいです。

キャッシュ操作

キャッシュのセット(8時間キャッシュするよ)
$cache_key = 'api_qiita:' . $id;
$this->cache()->set($cache_key, $data, time() + 8 * 3600);
キャッシュのゲット
$cache_key = 'api_qiita:' . $id;
$cache = $this->cache()->get($cache_key);

$id がUniqueなので、一つのメソッドだけでアカウントごとにキャッシュの保持を行うことができますね。

こちらを__invokeに組み込めば、キャッシュ機構もばっちしだと思います。

Qiitaサーバーへの負荷も軽減できますね。

まとめ

お疲れ様でした。いかがでしたか?

今回は、Qiita/RSSを題材にDrupalのController・API配信・キャッシュ機構についての実装をやってみました。

RSSを題材にやってみましたが、今回のようなRoutingの設定方法は他にも活かせる場面が多いはず 😎

キャッシュ設定に関しても、DrupalのEntity機構と組み合わせればもっと動的にGUIで設定できたり...。

いろいろできそうですね 😏

実は、このシリーズまだ終わりません。(え〜!!?)
次回は、Next.js でこのAPIを使ってレンダリングをしてみましょう。(え〜!!?)


シリーズ紹介

6
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?