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

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

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

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

PHP

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

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

Q&A

解決済

3回答

7040閲覧

Laravel5のforeachでキーが重複する時、最初の1度だけ実行してbreakする方法を教えてください

qwe001

総合スコア133

CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

PHP

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

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

0グッド

0クリップ

投稿2016/11/07 07:38

編集2016/11/07 07:42

環境

Laravel 5.3.10
PHP 5.6.22
CentOS 6.8
Postgresql 9.5.3

http://codepen.io/qwe001/pen/MbYPZb

していること

都道府県をDBから取得し、それとは別のDBにあるレコードの都道府県を比較、
都道府県の文字列が一致する場合、同じ都道府県のレコードを一覧表示

したいこと

都道府県が一致する場合、なので、都道府県テーブルとアイテムテーブルは一対多の関係。
当然ながら、一つの都道府県に複数のアイテムがくっついている。
そこで、一番最初のレコードの上に見出しとして都道府県名を1つだけ表示したい。

現在の実装

同じキーが二度続いたらbreakするような記述がしたいのですが、方法が思いつかず困っています。
現在のコードは以下のとおりです。

html+php

1<table class="items"> 2 <tbody> 3 @foreach($items as $item) 4 @foreach($prefs as $pref) 5 @if($pref -> name == $item -> pref) // DB上の都道府県名($pref -> name)とアイテムの都道府県($item -> pref)が一致した時 6 // ここに何か条件分岐を入れたいです。アイテムの都道府県が重複する場合、breakする、みたいな 7 <tr class="area"><th colspan="2">{{ $pref -> name }}</th></tr> // <tr class="area"><th colspan="2">東京都</th></tr> 8 @endif 9 @endforeach 10 <tr> 11 <th><a href="{{ $item -> id }}">{{ $item -> name }}</a></th> // <th><a href="1">●●●</a></th> 12 <td>{{ $item -> pref }} {{ $item -> address }}</td> // <td>東京都 渋谷区</td> 13 </tr> 14 @endforeach 15 </tbody> 16</table>

生成されるHTMLタグは以下のサイトで公開しています。

http://codepen.io/qwe001/pen/MbYPZb

サイト上にあるように、見出しにあたる都道府県の名前は1度以上は登場させたくないので、
何かのIF文あるいはCOUNT文でforeachを1度だけ繰り返してbreakする、みたいなものを想像しているのですが、
その条件式として適切なものが思い浮かばずに困ったため、今回質問した次第です。何卒ご教授をお願いいたします。

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

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

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

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

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

guest

回答3

0

ベストアンサー

もっとも良い方法は Archsted様の回答の通りですが、
一応、PHPコードだけで解決する方法を提示させていただきます。
(ralavelは不勉強な上に手元に実行環境が無いため、正常に動作するかは怪しいですが(^^;)

もし、現状、コントローラ側で以下のようにビューにデータを送っている場合、

php

1return view('XXX', array('items' => $items, 'prefs' => $prefs));

送信するデータを以下のように変更すると、

php

1$itemsPerPref = array(); 2foreach ($prefs as $pref) { 3 $itemsPerPref[$pref->name] = array(); 4 foreach ($items as $item) { 5 if ($item->pref === $pref->name) { 6 $itemsPerPref[$pref->name][] = $item; 7 } 8 } 9} 10 11return view('XXX', array('itemsPerPref' => $itemsPerPref));

テンプレート側では以下のようにすると、望む形に表示できると思います。

php

1@foreach($itemsPerPref as $pref => $items) 2 <tr class="area"><th colspan="2">{{ $pref }}</th></tr> 3 @foreach($items as $item) 4 <tr> 5 <th><a href="{{ $item -> id }}">{{ $item -> name }}</a></th> 6 <td>{{ $item -> pref }} {{ $item -> address }}</td> 7 </tr> 8 @endforeach 9@endforeach

ただし、$itemsの要素数が膨大だと、このコードの実行速度は惨憺たる結果になります。
なぜなら、この方法ではコントローラとビューのループが合計__(($prefsの要素数 + 1) × $itemsの要素数)__回、回るためです。

繰り返しになりますが、Archsted様の回答のように、DBからデータを取得する方法から見直すことをお勧めします。

投稿2016/11/07 09:29

KiyoshiMotoki

総合スコア4791

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

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

qwe001

2016/11/14 05:45

回答ありがとうございます。返信が遅くなり申し訳ありません。こちらの方法で期待通りのものが表示されました!ありがとうございます。 ですが、話し合いの結果都道府県の見出しは必要なくなったのでこちらの実装も不要となりました。。ただ、DBのデータ取得を見直す良い機会となり勉強になりました。ありがとうございます。またよろしくお願いいたします。
guest

0

仮に都道府県テーブルをprefsテーブル、アイテムテーブルをitemsテーブルとし、
それぞれに対応するPrefモデルとItemモデルを作るとします。

Prefモデルの中に、Itemモデルに対する1:多のリレーションを作ります。
itemsテーブルにpref_idにあたるカラムがあればいいのですが、どうやら無さそうに思えるので
(あんまりいい方法ではありませんが)お互いのテーブルのname列を結合条件とします。

PHP

1public function items() 2{ 3 return $this->hasMany('App\Item', 'name', 'name'); 4}

モデルの定義をしたあとは

PHP

1$prefs = Pref::with('items')->get();

のように都道府県レコードをアイテムレコードと一緒に取得し、まとめてviewに送れば、

PHP

1foreach ($prefs as $pref) { 2 // prefの表示とか 3 4 foreach ($pref->items as $item) { 5 // itemの表示とか 6 7 } 8 9}

こんな感じで、外側のループは都道府県の回数、内側のループはその都道府県のアイテムで回せるので
重複して都道府県の出力が出ないようにできると思います。

投稿2016/11/07 08:58

編集2016/11/07 08:59
Archsted

総合スコア452

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

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

0

laravelはまだ使ったことがないのでアルゴリズムだけでも手助けになればなと思い回答させて頂きます。

空の配列を作成し、1度だけ実行したい部分に入ったら、
最初に作成した空の配列に都道府県をpushします。

if文で「in_array」等を用いて一度入れたか都道府県チェックする。

などはいかがでしょうか。

投稿2016/11/07 07:45

mukkun

総合スコア882

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問