質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
date

dateは、date型や日付に関する関数や処理についてのタグです

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

2回答

2063閲覧

PHP array_filter関数を使ってデータの絞り込み後、比較して条件分岐を行いたい。

ddd_stage

総合スコア0

date

dateは、date型や日付に関する関数や処理についてのタグです

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2021/03/23 14:10

前提・実現したいこと

PHP(Laravel6)で健康管理をするためのwebアプリを作っています。
healthsテーブルにdate型の日付カラムをもたせており、ユーザーが登録した日付と同じシステム日付がビューにあった時に、該当のレコードを表示し、なければシステム日付のみを表示するといった機能を実装しているところです。

発生している問題・エラーメッセージ

そこでarray_filter関数を用いて、healthsからループでまわっている日のデータをフィルターにかけ、同じデータが存在する場合は該当のレコードを表示、なければシステム日付のみを表示という条件分岐を作っている際に、以下のようなエラーがでました。

ErrorException array_filter() expects parameter 1 to be array, object given (View: /var/www/health-manage-app/resources/views/health/index.blade.php)

該当のソースコード

実際のソースコードは以下になります。

index

1@php 2 $day = 1; 3@endphp 4 5@while ($day <= 31) 6 @php 7 $simple_date = strtotime(sprintf("%04d-%02d-%02d", $year, $month, $day)); 8 @endphp 9 10 @if($month != date("n", $simple_date)) 11 @break; 12 @else 13 @php 14 $ymd = date("Y-m-d", $simple_date); 15 @endphp 16 @endif 17 18 @php 19 $same_date = array_filter($healths, function($health){ 20 return $health['date'] == $ymd; 21 }); 22 @endphp 23 24 @if(isset($same_date)) 25 26 <tr> 27 <td>{{ $health->date }}</td> <td>{{ $health->temperature_mo }}</td> <td>{{ $health->temperature_ev }}</td> <td>{{ $health->cough }}</td> <td>{{ $health->dyspnea }}</td> <td>{{ $health->nasal }}</td> <td>{{ $health->throat }}</td> <td>{{ $health->headache }}</td> <td>{{ $health->diarrhea }}</td> <td>{{ $health->taste }}</td> <td>{{ $health->smell }}</td> <td class="text-ellipsis">{{ $health->other }}</td> <td><a href='/health/{{ $health->id }}'>詳細</a></td> <td></td> <td><a href='/health/action'>登録</a></td> 28 </tr> 29 30 31 @else 32 <tr> 33 <td>{{ $ymd }}</td> <td></td> <td></td> <td></td> <td></td> <td></td> <td></td> <td></td> <td></td> <td></td> <td></td> <td class="text-ellipsis"></td> <td><a href= '{{ route('health.create') }}'>登録</a></td> <td></td> <td><a href='/health/action'>登録</a></td> 34 </tr> 35 @endif 36 37 @php 38 $day++; 39 @endphp 40@endwhile

HealthController

1public function index(Request $request) 2 { 3 if($request->has('year') && !empty($request->year)){ 4 $year = $request->year; 5 }else{ 6 $date = date("Y-m-d"); 7 $year = date('Y', strtotime($date)); 8 } 9 10 if($request->has('month') && !empty($request->month)){ 11 $month = $request->month; 12 }else{ 13 $date = date("Y-m-d"); 14 $month = date('n', strtotime($date)); 15 } 16 17 if($request->has('day') && !empty($request->day)){ 18 $day = $request->day; 19 }else{ 20 $date = date("Y-m-d"); 21 $day = date('t', strtotime($date)); 22 } 23 24 if($request->has('uid') && !empty($request->uid)){ 25 $uid = $request->uid; 26 }else{ 27 $uid = Auth::user()->id; 28 } 29 30 $name = Auth::user()->name; 31 32 $healths = Auth::user()->healths()->get(); 33 34 return view('health/index', compact('uid','name','year','month','day','healths')); 35 } 36

試したこと

https://www.suzu6.net/posts/162-php-array_filter/#%E9%96%BE%E5%80%A4
上記の記事と同じ構造であると判断し、今回のarray_filter関数のコードを書きました。
エラーの内容として、ひとつ目のパラメータには配列を入れないといけませんよ、という意味と認識しましたが、コントローラにて$healthsを定義してviewに渡しているため、既に連想配列になっているはず(echoで$healthsを出力すると所持データを連想配列で表示できることは確認済み)と考えています。
PHP初学者のため、至らない質問になってしまっているかと思いますが、わかる方いらっしゃいましたらご教示いただけると幸いです。
よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

PHP7.2 Laravel6

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

すごい基本的なことを言います。このエラーメッセージは読み解けるようにしといた方がいいです。

ErrorException array_filter() expects parameter 1 to be array, object given

このメッセージですが

■■■■■ expects parameter to @ to be ●●●●●, ××××× given

■■■■■の@つ目の引数は●●●●●にすべきなんだけど、×××××が入ってるよ!ということです。これは頻出するエラーメッセージなので覚えておくといいでしょう。

ではarray_filter関数ですが、PHPのarray関数(array_filterなど)は配列しか処理できません。あとは別の方の言う通り、配列に変える対処をしていくといいでしょう。

投稿2021/03/24 00:32

FKM

総合スコア3640

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ddd_stage

2021/03/24 02:01

FKM様 コメント、ご指摘いただきありがとうございます。 頻出エラーとのこと、今後同じエラーが発生した際にすぐ解決できるよう今回の件で身につけます。 kawax様のご指摘の通り、toarray()を使って配列にして実行しましたが、配列自体を複数回繰り返してしまう状況です。 kawax様の回答への返信に、現在の状況とコードを記載致しましたので、何か解決方法がお分かりでしたらご教示いただけますと幸いです。 よろしくお願いいたします。
guest

0

こうすればarrayではないことはわかる。

php

1$healths = Auth::user()->healths()->get(); 2dd($healths);

Laravelは表示時に自動的に変換することがあるので元のデータが何かしっかり確認が必要。

一番簡単な解決はtoArray()だけど(use($ymd)も必要)

php

1$same_date = array_filter($healths->toArray(), function($health) use($ymd) { 2 return $health['date'] == $ymd; 3});

それ以外も基本的なことが分かってない。

・Laravelで日時はCarbonを使うのでdate()は使わない。
Laravel使う前にPHPの知識は必須だけど実際にLaravel使う段階ではPHPの常識は捨てないといけないのが厄介なところ。

・第二引数でデフォルトは頻繁に出てくるので絶対に覚える。6行も使ってる箇所が1行に減る。

php

1$year = $request->input('year', now()->year);

・bladeで@phpが多いのは悪いコードの兆候。

・@whileではなくrangeとforeachの方が分かりやすい。

@foreach(range(1, 31) as $day)

投稿2021/03/23 14:45

kawax

総合スコア10377

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ddd_stage

2021/03/24 02:08 編集

丁寧なご回答をいただきありがとうございます。 基本的な部分ができていないことも改めて実感しました。 いただいたご指摘を受けて、toarray()とuse($ymd)を使用したコードに書き換えましたが、以下のエラー表示となりました。 Undefined variable: health(viewで展開する際に、$healthというものが定義されていない) そこで、配列として定義した$healthsをforeach文で、 @foreach(range(1, 31) as $day) //省略 @if(!empty($same_date)) @foreach($healths as $health) <tr> <td>{{ $health->date }}</td> </tr> @else <tr> <td>{{ $ymd }}</td> </tr> @endif @php $day++; @endphp @endforeach と書いたところ、$same_dateで定義したフィルターが正しく動いている(該当の日付の時のみデータを表示)ことは確認できたのですが、以下のように所持しているデータの数だけ繰り返してしまいます。 3/1~3/21 データがないため空欄 3/22 データ表示 3/23 データ表示 3/22 データ表示 3/23 データ表示 3/24~3/31 データがないため空欄 よって、foreachで回す必要がないことが考えられるのですが、その場合の$healthsのデータ展開はどのように行うのかが分かりません。 3/22,23のデータを1件ずつのみ表示させたい場合、どのようにコードを書けばよろしいでしょうか? よろしくお願いいたします。
FKM

2021/03/24 02:33 編集

外側のループ while($day < 31)の分だけ、回数分ループを繰り返してしまってるからです。 つまり$day == 22のときと$day == 23のときにarray_filterの該当分を吐き出してるわけです。 これを防ぐためには、元のループの$dayと取得した$ymdのdにあたる部分が一致しているかどうかも 判定文に盛り込む必要があるのでは。 すごい効率悪いですけど。
ddd_stage

2021/03/24 02:48

ご回答いただきありがとうございます。 外側のループの分だけ繰り返しているということは理解できましたが、判定文を盛り込む必要なく(foreachを使わずに$healthを展開する)実装できる方法は他に何かありますでしょうか? 初学者の単純な施策として、 <tr> <td>{{ $healths->['date'] }}</td> </tr> としてみたら展開できるのではないかと考えたのですが、dateが未定義であるというエラーメッセージの表示がでます。また、そもそもこの展開方法でできたとしても、外側のループ while($day < 31)の分だけ、回数分ループを繰り返してしまっている状況は変わらないのかな?と困惑している状況です。 もし判定文を盛り込むしかない場合、どのようなコードで実装できるかをご教示いただけますと幸いです。 よろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問