20220113のlaravelに関する記事は7件です。

Laravel・ヘルパー関数Optionalについて

とあるテーブルのカラムに値が入っていないと Trying to get property of non-object このようなエラー文言が画面に現れます。 optionalヘルパー関数を使う事でこのエラーを解消する事ができます。 例としてとあるテーブルを元に解説していきます。 データベース 例) ・itemsテーブル ・stocksテーブル itemsテーブルとstocksテーブルは1対1の関係性です。 stockの中身は空だとします。(nullの場合) item.blade.php {{ $item->stock->stock }} itemテーブルに紐づいたstockテーブルのstockカラムを取得したいのですが、stockカラムがnullの為、上記コードでは画面に『Trying to get property of non-object』 このようなエラー文言が出てしまいます。 解決策 item.blade.php {{ optional($item->stock)->stock }} このようにoptionalヘルパー関数を付ける事により、stockカラムの中がnullだとしてもエラーにはならずviewが表示されます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel + Vue.js でVuexを使えるようにする

経緯 踏切発車でVuexを入れたけど使い方よくわからない。 試行錯誤で無駄な時間を費やしたのでここに記す。 環境 Laravel 6系 (APIとして使用) Vue.js 2系 Docker 前提:vue導入済み シナリオ ログインユーザー情報取得を想定 /api/userを叩くとログインユーザーの情報(id, name)のjsonが返ってくる。 取得したユーザー情報を表示する。 準備 Vuexのインストール $ npm install vuex /app/resources/js配下にstore.jsを追加 /app/resources/js/store.js import axios from 'axios'; import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const state = { user: [] } const mutations = { getUser(state) { axios.get('apiのURL') .then(res => { state.user = res.data; }).catch(err => { console.log(err.response); }); } } const getters = { getUsername(state) { return state.user.name; } } const actions = { getUserAction(ctx) { ctx.commit('getUser'); } } export default new Vuex.Store({ state, mutations, getters, actions }); /app/resources/js/app.jsに以下を追記 /app/resources/js/app.js import Vue from 'vue'; import store from './store'; // 追記 import ExampleComponent from './components/ExampleComponent'; /** * 省略 */ const app = new Vue({ el: '#app', store, // 追記 components: { ExampleComponent, } }); 呼び出し 以下コンポーネントで呼び出すとき /app/resources/js/component/ExampleComponent.vue <template> <!-- 省略 --> <p>{{ this.$store.getters.getUsername }}</p> ・・・ ① <!-- 省略 --> </template> <script> export default { created() { this.$store.dispatch('getUserAction'); // ・・・ ② } } </script> ① - ゲッターでユーザー名を取得する。 ② - DOM作成前にイベント発火(mounted()だと表示が遅れて微妙なのでcreated()を使用している) 多分これで動く。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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で続きを読む

【Laravel】Carbonの変な挙動

変な挙動 Tinkerで今月の最初の日付と最終日をそれぞれ別の変数に入れて出力 > php artisan tinker Psy Shell v0.10.9 (PHP 7.4.4 — cli) by Justin Hileman >>> $now = Carbon\Carbon::now(); => Carbon\Carbon @1642055469 {#3917 date: 2022-01-13 15:31:09.011838 Asia/Tokyo (+09:00), } >>> $now_first_day = $now->startOfMonth(); => Carbon\Carbon @1640962800 {#3917 date: 2022-01-01 00:00:00.0 Asia/Tokyo (+09:00), } >>> $now_end_day = $now->endOfMonth(); => Carbon\Carbon @1643641199 {#3917 date: 2022-01-31 23:59:59.999999 Asia/Tokyo (+09:00), } >>> echo $now_first_day; 2022-01-31 23:59:59⏎ >>> echo $now_end_day; 2022-01-31 23:59:59⏎ あれ、$now_first_dayの値も最終日になってる startOfMonth()は日付を返してるわけじゃなかった。 指定月の最初の日付を返してくれるメソッドと勘違いしてた。dateを書き換えるメソッドだった。 んでもってオブジェクトは参照渡しだから値が変わると。変な挙動も何も無知なだけでした。ちゃんちゃん
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[備忘録]Laravel8系にMiniOを導入する際に躓いた

個人的な備忘録です。 やりたいこと Laravel8のsailにMniOを導入 躓いたこと docker-compose.yml記述 ポート自動設定 リダイレクトループ 解決策 docker-compose.yml記述 environmentの記述は下記の通り MINIO_ROOT_USER: ${自身で設定} MINIO_ROOT_USER: ${自身で設定} ポート自動設定 docker-compose.yml内のminio定義で、command記述を下記にする ["server", "/data", "--console-address", ":9001"] /dataは以前、/exportだった --console-addressオプションを付けないと自動でポートが設定される仕様に変更があった リダイレクトループ ポート自動設定と被るが、/dataにしないといけなかった模様 合わせてポート定義を1つから2つに増やした "9000:9000" "9001:9001" 上記2つを同時に行うことで、リダイレクトループは無くなったが、どちらか片方だけでもいけたかもしれない。(未検証 MiniO使い方 http://localhost:9001アクセス ログイン ログイン情報は自分で定義している(.envのAWS_ACCESS_KEY_ID等 メニューからバケット選択 Create Bucket+ボタン押下 任意のバケット名を入力後Create Bucketボタン押下 バケットを作成後、laravel側で取得などの処理を記述 取得例: $directories = Storage::disk(self::STORAGE_DISK_S3)->directories(); 参考 MinIOの管理画面にアクセスすると別ポートにリダイレクトされる件の解消 MinIO のバージョンアップに伴い変更点があった LaravelでStorageでS3(minio)へアクセスする
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む