PHPでモダンな感じで HTTP 通信するなら何?みたいな話をいつだったかしていました。
どうやら Guzzle が流行ってるらしい、とのことだったので、試しに Authorizationリクエストヘッダも含めた HTTP 通信をしてみることにしました。
なお、5年ぶりくらいに PHP を触ったので、連想配列を書くだけでも苦戦してました(他言語の書き方に慣れすぎたか…)。まあ思い出したけど。
やったこと
まず Docker で Guzzle を入れる
正直ここが一番大変だったといっても過言ではないです。
背景としては、特に普段から PHP を書いていないのでローカルに開発環境は不要と思い、実行環境だけあればよい気持ちになったためです。
Overview — Guzzle Documentation を見ている限りでは、 composer で入れるのが良いらしいですね。
ちょっと調べると composer も Docker Image があることを知りました。やったー。
というわけで下記の2つを使ってマルチステージビルドしました。
- php
- 気分的に
php:8.0-fpm-buster
にした - buster イメージのためか git が入っていなかった、 composer は git を使うので git をいれるようにする
- 気分的に
- composer
- 下のほうに書いてあるが、マルチステージビルドするには下記がいいよと書かれている
-
COPY --from=composer /usr/bin/composer /usr/bin/composer
- ついでにそれっぽい Qiita 記事も見つけた Docker に Composer をインストールするベストプラクティス(と解説) - Qiita
というわけで Dockerfile は下記になりました。
FROM php:8.0-fpm-buster # composer はマルチステージビルドで持ってくる # refer: https://qiita.com/yatsbashy/items/02bbbebbfe7e5a5976bc COPY --from=composer:latest /usr/bin/composer /usr/bin/composer # composer need git RUN apt-get update && apt-get install -y git RUN composer require guzzlehttp/guzzle:^7.0 COPY . . RUN chmod u+x entrypoint.sh ENTRYPOINT ["/var/www/html/entrypoint.sh"] # RUN ["php", "main.php"]
よくわかってないのですが、なぜか WORKDIR が /var/www/html/
になっているので(composerのせいか?) ENTRYPOINT はそこに合わせています(デバッグするときは ENTRYPOINT 外して、雑に exec -it {image_id} bash
で入ってデバッグしていた)。
Guzzle でリクエストをする
Qiita の API でも試しに叩いてみることにします。認証しているユーザーを返す API がある GET /authenticated_user のでそれをたたいてみることにします。
基本的には Client を作って、リクエストして、結果を受け取る形です。下記のページを参照に作っていきます。
出来上がったものがこちら。
<?php require 'vendor/autoload.php'; $token = getenv('QIITA_ACCESS_TOKEN'); $client = new \GuzzleHttp\Client( [ 'base_uri' => 'https://qiita.com', 'timeout' => 2.0, ] ); $headers = [ 'Content-Type' => 'application/json;charset=utf-8', 'Authorization' => 'Bearer '.$token, ]; $res = $client->request( 'GET', '/api/v2/authenticated_user', [ 'headers' => $headers ] ); echo $res->getStatusCode()."\n"; echo $res->getHeaderLine('content-type')."\n"; echo $res->getBody()."\n";
token は直打ちするとよろしくないので、環境変数からとる形にしています。
環境変数を渡しつつ実行する
最後に虚無みたいな entrypoint.sh を作っておくことにします。
#!/bin/bash
php main.php
まずはビルドします。
❯ docker build . -t php-practice Sending build context to Docker daemon 4.608kB Step 1/7 : FROM php:8.0-fpm-buster ---> 4ebd60322a2b Step 2/7 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer ---> Using cache ---> 49f3a96a6383 Step 3/7 : RUN apt-get update && apt-get install -y git ---> Using cache ---> 0bd8cb7267ee Step 4/7 : RUN composer require guzzlehttp/guzzle:^7.0 ---> Using cache ---> ea788036ebab Step 5/7 : COPY . . ---> Using cache ---> a5fb0b2fa934 Step 6/7 : RUN chmod u+x entrypoint.sh ---> Using cache ---> 3db87772286c Step 7/7 : ENTRYPOINT ["/var/www/html/entrypoint.sh"] ---> Using cache ---> ee0a466366fd Successfully built ee0a466366fd Successfully tagged php-practice:latest
で、うまくいったら run します。 ENTRYPOINT を指定してるし、 run したら消していいはずなので --rm
つけてます。
トークンは Qiita のユーザーページから発行してください。
❯ docker run -e QIITA_ACCESS_TOKEN=${PEKOPEKO} -t php-practice --rm 200 application/json; charset=utf-8 {"description":"えんじにゃー。ぷりぷりかしこま。Pythonしかできない。","facebook_id":"","followees_count":19,"followers_count":21,"github_login_name":"yumechi","id":"yumechi","items_count":9,"linkedin_id":"","location":"東京","name":"Senri Yumechi","organization":"い","permanent_id":72473,"profile_image_url":"ほげほげ","team_only":false,"twitter_screen_name":"__yumechi","website_url":"https://namonakimichi.hatenablog.com/","image_monthly_upload_limit":104857600,"image_monthly_upload_remaining":104857600}
ちょっとやばそうなところは雑にマスクしましたが、無事に実行できました。やったね。
まとめ
やっぱり Docker ! マルチステージビルド ! はいいですね。ローカル環境が汚れにくいし、再現性もあっていい感じです。
環境変数も実行時に入れることによって、挙動を制御することもできるので、活用していきたいですね。
そして Guzzle ですが、ヘッダーの設定、リクエストの受付、そのあたり見ても他の言語の通信と大差ない感じで扱えて非常に楽でした。
cURL でリクエストする方法も知っていますが、 Guzzle にはどうやらまだ使いこなせていない機能でいいもんがたくさんありそうです。
PHP でなにかつくるかはわかりませんが、頭の片隅には入れておこうと思います。
追記
静的解析も少しやったんだった。この記事を参考にした。
php -l <filename>
はガバガバなので何も出なかった。
phpcs を試して多少おこられたので直しました( main.php はこれに従って直した)。
ほかについては試してませんが、 CI とか回すときにコードチェックもついでにできるようになるといいかもしれないですね (希望的観測)。
これで今度こそ終わり。