20220113のPHPに関する記事は5件です。

Laravelで楽天APIのリクエスト制限を対策する

はじめに Laravelで楽天APIを使ったWEBアプリを開発していたところ、APIを提供している楽天ウェブサービスのヘルプページでリクエスト制限があることを知りました。 1つのapplication_idにつき、1秒に1回以下のリクエストとしてください。 アフィリエイトサイトとして高い成果が見込まれる場合は制限緩和ができるみたいですが、そうでない場合はAPIの使用が制限されています。 もし継続的に制限を超えたリクエストを行った場合はアプリIDが利用停止になる可能性があるみたいなので対策が必要だと考えました。 楽天APIの実装方法についての記事はいくつかありましたが、リクエスト制限まで触れているものは見かけなかったので、自分なりの対策を備忘録として残しておきます。 環境 PHP 7.4.27 Laravel 8.78.1 楽天APIの実装 アプリIDを取得 楽天APIの利用にはアプリIDが必要になります。 楽天ウェブサービスでアプリを新規登録しアプリIDを発行します。 SDKをインストール 次にSDK(ソフトウェア開発キット)を導入します。 PHPで楽天APIを使うための機能がパッケージされているものがあるのでそちらを使用します。 Laravelのプロジェクトディレクトリ直下のcomposer.jsonに下記を追加します。 composer.json "require": { (略) "rakuten-ws/rws-php-sdk": "1.*" } SDKをインストールするため下記のコマンドを実行します。 $ composer install インストールできていればvendorディレクトリにrakuten-wsが追加されています。 環境設定 取得したアプリIDを.envファイルに設定します。 RAKUTEN_APPLICATION_ID='アプリケーションID' configで中継しておきます。 config/services.php 'rakuten' => [ 'application_id' => env('RAKUTEN_APPLICATION_ID'), ], コントローラを作成 楽天検索の実行部分を実装します。 楽天ブックス書籍検索APIでの検索例です。 なお検索フォームや商品データ取得後の表示処理などについては割愛しています。 SearchController.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Arr; use RakutenRws_Client; class SearchController extends Controller { public function index(Request $request) { // RakutenRws_Clientインスタンスを作成 $client = new RakutenRws_Client(); // 定数化 define("RAKUTEN_APPLICATION_ID", config('services.rakuten.application_id')); // アプリIDをセット $client->setApplicationId(RAKUTEN_APPLICATION_ID); // リクエストから検索キーワードを取得 $inputs = array_filter($request->only(['title', 'author'])); $items = []; if (count($inputs) > 0) { // 楽天ブックス書籍検索を実行 $response = $client->execute('BooksBookSearch', $inputs); if ($response->isOk()) { foreach($response as $item) { // 取得したいパラメータでフィルタリングして保存 $items[] = Arr::only($item, [ 'title', 'author', 'itemPrice', 'itemUrl', 'mediumImageUrl', ]); } } else { echo 'Error:'.$response->getMessage(); } } // 省略 } } ここまでで楽天APIで商品データを取得してくることができました。 ただこのままでは冒頭で記述したようにリクエスト制限値を超えるリクエストが送られて来た場合に、アプリIDが利用停止になってしまう可能性があるため追加で対策していきます。 リクエスト制限対策 どうやって対策しようかと調べていたところ、Laravel公式ドキュメントのキャッシュのページにあるロック管理の機能がぴったりだったのでこれを使って実装しました。 リクエスト制限対策後のコードを先に記載しておきます。 SearchController.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Arr; use RakutenRws_Client; use Illuminate\Contracts\Cache\LockTimeoutException; // 追加 use Illuminate\Support\Facades\Cache; // 追加 class SearchController extends Controller { public function index(Request $request) { // 省略 if (count($inputs) > 0) { // ロックを1秒間取得 $lock = Cache::lock('rakuten_api', 1); try { // ロック取得を最大5秒待つ $lock->block(5); $response = $client->execute('BooksBookSearch', $inputs); if ($response->isOk()) { foreach($response as $item) { $items[] = Arr::only($item, [ 'title', 'author', 'itemPrice', 'itemUrl', 'mediumImageUrl', ]); } } else { echo 'Error:'.$response->getMessage(); } } catch (LockTimeoutException $e) { // ロック取得失敗時の処理 } } // 省略 } } 追加した部分については以下の通りです。 // ロックを1秒間取得 $lock = Cache::lock('rakuten_api', 1); Cache::lockメソッドによって第一引数の名前のロックを第二引数で指定した秒数取得した状態になります。 ロックを取得している間は別のプロセスがロックを取得できなくなっています。 try { // ロック取得を最大5秒待つ $lock->block(5); // ロック取得時の処理 } catch (LockTimeoutException $e) { // ロック取得失敗時の処理 } blockメソッドはロックを取得していない場合、処理を止めて指定の秒数ロックが解放されるのを待ちます。 ロックが解放されればロックを取得して処理を進めますが、時間内にロックが解放されなければLockTimeoutExecptionを投げます。 これで同時にリクエストがきた場合でも楽天検索の実行間隔が1秒以上離れるため、制限に引っかからなくなったのではないかと考えています。 まとめ Qiita初投稿で至らない点もあったとは思いますが最後まで読んでいただきありがとうございます。 今回はリクエスト制限に焦点を当てましたが、さらにAPIへの理解を深めるために楽天以外のものも使っていきたいと思いました。 間違いや改善点などがあればご教示いただけますと幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel/Carbon 期間を指定して日付文字列の配列取得する

laravel/Carbon 開始日付・終了日付指定し、その期間の文字列配列を取得する laravel5.7を使用している案件でCarbonPeriodをuseしたら「Class 'CarbonPeriod' not found」とエラー。 バージョンによるものなのか、どうエラー解消するのか、パっと分からなかったので プロジェクトの日付操作はCarbonで統一されてるみたいなので従来どおりCarbon使って期間の文字列配列生成しました。 また同じ事が起きたとき用にテンプレとして書き残しとこーって ※逆期間非対応 use Carbon/Carbon; $startDateTime = new Carbon('2022-01-01'); $endDateTime = new Carbon('2022-01-08'); $dates = []; $diffDays = $startDateTime->diffInDays($endDateTime); for ($i = 0; $i <= $diffDays; $i++) { $dates[] = $startDateTime->format('Y-m-d'); //ここで日付フォーマット定義 $startDateTime->addDays(); } var_dump($dates);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】Requestで取得できる値の型を変換する必要性は?

概要 本記事は、PHPフレームワークLaravel入門 第2版で学習している中の疑問・つまづきの備忘録です。 今回はLaravelにおいてRequestで取得できる値の型を変換する必要性についての疑問をまとめます。 今回の疑問 コントローラー内のアクションメソッドで引数として取得できるRequestに含まれるパラメータの型を変換する必要性があるのか、その理由は何か、疑問を持ちました。 詳細はサンプルコードにて記載します。 サンプルコード このサンプルコードはPHPフレームワークLaravel入門 第2版で用いられていたものです。 今回の疑問はmin変数の初期化に用いている値、$request->input * 1 について、*1しなくても正常に動くにも関わらず、なぜ*1しているのか調査してみました。 なお、ここでの取得している入力項目は年齢です。 PersonController.php public function search(Request $request) { //この*1はなぜ必要? $min = $request->input * 1; //   $min = $request->input; *1しなくても同じ結果を得られた $max = $min + 10; $item = Person::ageGreaterThan($min)->ageLessThan($max)->first(); $param = ['input' => $request->input, 'item' => $item]; return view('person.find', $param); } PHPフレームワークLaravel入門 第2版 試したこと 以下のようにvar_dump()で確認したところ元々取得されるているのはstring型、*1するとint型になっていました。 したがって、年齢をint型に変換したい理由があるということです。 PersonController.php public function search(Request $request) { $min = $request->input * 1; $max = $min + 10; var_dump($request->input);//////string(2) "30" と出力 var_dump($request->input * 1);//////int(30) と出力 $item = Person::ageGreaterThan($min)->ageLessThan($max)->first(); $param = ['input' => $request->input, 'item' => $item]; return view('person.find', $param); } 年齢をint型に変換したい理由とは 実験的に以下のようなコードを試してみました。 addToInputメソッドを宣言し、引数をint型に指定しています。 PersonController.php public function search(Request $request) { $min = $request->input; ///こちらはエラーが発生する //$min = $request->input * 1; ///こちらは正常に処理される $max = $min + 10; $item = Person::ageGreaterThan($min)->ageLessThan($max)->first(); $param = ['input' => $request->input, 'item' => $item]; return view('person.find', $param); } //実験用コード、引数はint public function addToInput(int $num) { return $num * 10; } 実行したところ、以下のエラーが発生しました。 引数$numはint型でないといけないと怒られています。 再度、最初のサンプルコードに示したように*1したところ、エラーは解消されました。 まとめ 今回$request->input * 1のように年齢をint型に変換しているのは、変数の型を意識して使用することで想定外のエラーを防ぐ目的があると考えられます。 サンプルコードの時点ではたまたまstring型のままでも問題なく動作しましたが、今回実験したaddToInputメソッドのように処理の内容によってはエラーとなる可能性があります。 PHPは型の相互変換ができますが、それに頼りすぎると良くないですね。 開発の際には今使用している値の型は何なのか、意識することが重要です。 参考文献 PHPフレームワークLaravel入門 第2版
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPのバージョンが勝手に変更されてMongoDBにアクセスできなくなった話

※アップデート 2022年1月15日:apt upgradeでパッケージが更新されないようにする方法を追記しました 症状 突然MongoDBへアクセスができなくなったしまった PHPのドライバが対応していないっぽい 解決 PHPのバージョンを確認 $ php -v PHP 8.0.12 (cli) (built: Oct 22 2021 12:34:00) ( NTS ) Copyright (c) The PHP Group Zend Engine v4.0.12, Copyright (c) Zend Technologies with Zend OPcache v8.0.12, Copyright (c), by Zend Technologies PHP8.0.12はアウト もともとはPHP7.2で動いていた PHP8 ➢ PHP7.2へダウングレードする 存在するPHPのバージョン一覧を確認 $ ls /usr/bin | grep -i php dh_phpcomposer dh_phppear jsonlint-php php php7.2 php7.4 php8.0 php-config php-config7.2 php-config7.4 phpize phpize7.2 phpize7.4 php7.2へ変更する まず現行動いているphp8.0を無効にする $ sudo a2dismod php8.0 [sudo] password for sugimoto: Module php8.0 disabled. To activate the new configuration, you need to run: systemctl restart apache2 そしてphp7.2を有効にする $ sudo a2enmod php7.2 Considering dependency mpm_prefork for php7.2: Considering conflict mpm_event for mpm_prefork: Considering conflict mpm_worker for mpm_prefork: Module mpm_prefork already enabled Considering conflict php5 for php7.2: Enabling module php7.2. To activate the new configuration, you need to run: systemctl restart apache2 php7.2に切り替えを実施 $ sudo update-alternatives --set php /usr/bin/php7.2 update-alternatives: using /usr/bin/php7.2 to provide /usr/bin/php (php) in manual mode Apache2の再起動 $ sudo systemctl restart apache2 確認 変わっているのでOK データも見れているのでOK 追記:apt upgradeでパッケージが更新されないようにする方法! 今回の原因は不意なapt upgradeをした結果発生したものかと思いまして,その際にパッケージが更新されないようにする方法を見つけました. こちらの記事を参照にしています つまりパッケージを $ sudo apt-mark hold (php7.2系) に固定することで勝手にアップデートされることはなくなりそうです!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Mac(PC)にてバックスラッシュ(\)を入力する方法

はじめに こちらの投稿は、Apple社のデスクトップPC、iMacに付属されているキーボード「Magic Keyboard(JIS)」をお使いの方に向けてです。 環境 ・macOS バージョン11.6にて動作確認をしています。 バックスラッシュの入力に仕方 macOSを付属のキーボード(JISキーボード)お使いの場合、バックスラッシュの入力の仕方は、 ・キーボードの左下にある、「option」+右上にある「¥」 どういうときに使うか ・主にプログラミングを描くときに使います。 ・PHPのエスケープシーケンスをするときに使います。 ・一つのタグの中に、シングルクォーテーション('')やダブルクォーテーション("")を複数個使うことは出来ないため、 <?php echo 'I'm Taro'; ?> などと入力しようとするとエラーが出てしまうので、それを回避するために <?php echo 'I\'m Taro'; ?>と入力することでエラーを回避することができます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む