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

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

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

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

5回答

2967閲覧

PHPのforeach文での4項目ずつDivタグに囲んで繰り返し表示したい

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2017/09/01 23:13

編集2017/09/01 23:30

phpのforeach文を使って4項目ずつDivタグに囲んで繰り返し表示出来るようにしたいのですが、思うように動かないため質問しました。

現在、データベースに登録された名前を下記の書き方ですべて表示出来ています。

php

1<?php 2foreach ($records as $record) { ?> 3 <?php echo $record['name'] ?> 4 <?php } ?> 5

現状だとそのまま9人目、8人目、7人目・・・といったように表示されているため、
データベースに登録された名前をforeachで繰り返し4人ごとdivで囲んで表示したいと考えています。
色々やったのですが、9人目9人目9人目9人目と表示されてしまったり、エラーが出てしまったり。。

html

1<div> 2 9人目 3</div> 4 5 <div> 68人目 77人目 86人目 95人目 10</div> 11<div> 124人目 133人目 142人目 151人目 16</div> 17 18 19下記のコードでは同じものが4つずつ表示されてしまいました。 20また、エラーが出てしまったコードについては、書いては消しを繰り返したため 21残ってないです。。 22```php 23<?php 24foreach ($records as $record) { ?> 25<div> 26<?php echo $record['name'] ?> 27<?php echo $record['name'] ?> 28<?php echo $record['name'] ?> 29<?php echo $record['name'] ?> 30</div> 31 <?php } ?>
回答のほど宜しくお願いします。

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

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

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

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

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

unau

2017/09/01 23:18

試してみたコードも是非、載せてください。
退会済みユーザー

退会済みユーザー

2017/09/01 23:31

とんど実行しては消しの繰り返しだったため、覚えているコードのみコードを記載しました。
guest

回答5

0

foreach 文を使ってデータベースから取得した結果を出力するのは出来ているので、そこに4つ区切りに <div>, </div> を挿入するようなコードを加えればよいと思います。

説明のため、まず表示するだけのサンプルコードを示します:

php

1<?php 2// 表示するだけのコード 3$records = [ 4 ['name' => '9人目'], ['name' => '8人目'], ['name' => '7人目'], ['name' => '6人目'], ['name' => '5人目'],['name' => '4人目'], ['name' => '3人目'], ['name' => '2人目'], ['name' => '1人目'] 5]; 6?> 7<?php foreach ($records as $i => $record): ?> 8 <?= htmlspecialchars($record['name']).PHP_EOL ?> 9<?php endforeach; ?>
// 結果 9人目 8人目 7人目 6人目 5人目 4人目 3人目 2人目 1人目

で、ここに4つおきに <div>, </div> を挿入するわけですが、方法を考えるのはコーディングというより、どちらかというと算数と頭の体操です。

まず先頭から4つおきに <div> を入れるなら、4の倍数(4n)になったときに <div> を出力すればよさそうです。つまり判定式は $i % 4 === 0 です。また </div> は 4n-1 になったときに出力します。判定式は $i % 4 === 3 です。ただこのままですと要素数が4の倍数ではない場合にタグが閉じられないため、最後にも閉じタグを挿入するのを忘れないでください。

結果的にこんなコードになります:

php

1<?php foreach ($records as $i => $record): ?> 2<?= $i % 4 === 0 ? '<div>'.PHP_EOL : null ?> 3 <?= htmlspecialchars($record['name']).PHP_EOL ?> 4<?= $i % 4 === 3 || $i === count($records) - 1 ?'</div>'.PHP_EOL : null ?> 5<?php endforeach; ?>
// 結果 <div> 9人目 8人目 7人目 6人目 </div> <div> 5人目 4人目 3人目 2人目 </div> <div> 1人目 </div>

あとは同じ要領で、今度は末尾から4つ区切りを行う方法をご自身で考えてみてくださいcount($records)-$i で残りの要素数を把握できるので、役に立ちそうです。


ちなみにデータベース(MySQL, PostgreSQL)やデータベースドライバの設定によっては、$i や count() が効かない場合があります。そのときは自前でカウントを行って下さい。

カウンター($i)が使えない場合は $i = 0; と初期化しつつ、foreachのループ内で $i++; と手動カウントすればOKです。

count($records) が使えない場合は、データベースから取得した全結果を一度配列にいれて count() してください。

投稿2017/09/02 00:37

編集2017/09/02 01:47
miyahan

総合スコア3095

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

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

退会済みユーザー

退会済みユーザー

2017/09/02 02:47

わかりやすく丁寧に説明していただきありがとうございます!! 自分の実現したかったことが考え方1つでここまで短いコードで出来るとは思いませんでした! コード含め、今後に役立てさせていただきます!!
guest

0

miyahan さんの回答が好きですけど、count がループの中に入ってるんで、外出にしたかったのと、外に出したんならなんとなく while じゃないかなぁと思って作ってみました。

php

1<?php 2$records = [ 3 [ 4 'name' => '9人目', 5 'age' => 20, 6 ], 7 [ 8 'name' => '8人目', 9 'age' => 21, 10 ], 11 [ 12 'name' => '7人目', 13 'age' => 22, 14 ], 15 [ 16 'name' => '6人目', 17 'age' => 23, 18 ], 19 [ 20 'name' => '5人目', 21 'age' => 24, 22 ], 23 [ 24 'name' => '4人目', 25 'age' => 25, 26 ], 27 [ 28 'name' => '3人目', 29 'age' => 26, 30 ], 31 [ 32 'name' => '2人目', 33 'age' => 27, 34 ], 35 [ 36 'name' => '1人目', 37 'age' => 28, 38 ], 39 ]; 40 $count = count($records); 41 $i = $count; 42?> 43<?php while ($i > 0):?> 44<?= $i % 4 === 0 || $i === $count ? '<div>'.PHP_EOL : null ?> 45<?= $i % 4 . ':' . htmlspecialchars(each($records)['value']['name']).PHP_EOL ?> 46<?= $i % 4 === 1 ?'</div>'.PHP_EOL : null ?> 47<?php $i -= 1 ?> 48<?php endwhile ?>

結果、each とか使って、あんまりきれいじゃないw

投稿2017/09/02 02:15

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

miyahan

2017/09/02 02:44

「OPcacheさんがなんとかしてくれるだろう」と軽く考えていましたが、ちゃんと調べると不変式をループ外に追い出す最適化はしてくれないようですね。たしかに配列が巨大だと無視できないコストになりそうです。
退会済みユーザー

退会済みユーザー

2017/09/02 02:48

Web 出力なんで、でかいはずないと思いますけどね。本件に限れば、難癖レベルですw
guest

0

array_chunk()で配列をあらかじめ4つの要素に分割してから、for()<div>タグを出力する外側に対応する配列をループします。そして、各4つの要素に対応する連想配列をforeach()で出力します。

下記コードの最下部コメントの「出力:」部分がarray_chunk()した連想配列です。

php

1// $records連想配列 2$records = array( 3 array('name' => '1人目'), 4 array('name' => '2人目'), 5 array('name' => '3人目'), 6 array('name' => '4人目'), 7 array('name' => '5人目'), 8 array('name' => '6人目'), 9 array('name' => '7人目'), 10 array('name' => '8人目'), 11 array('name' => '9人目'), 12); 13 14// $records配列を4つの要素で分割(インデックスはそのまま) 15$array = array_chunk($records, 4, true); 16 17for ($i=0; $i<count($array); $i++) { 18 echo "<div>\n"; 19 foreach ($array[$i] as $record) { 20 echo "\t".$record['name']."\n"; 21 } 22 echo "</div>\n"; 23} 24 25echo '<pre>'; 26echo '$array : '; 27print_r($array); 28echo "\n"; 29echo '</pre>'; 30 31// 出力: 32// $recordsのインデックスを保持 33// 34// $array = array( 35// array( 36// '0' => array('name' => '1人目'), 37// '1' => array('name' => '2人目'), 38// '2' => array('name' => '3人目'), 39// '3' => array('name' => '4人目'), 40// ), 41// array( 42// '4' => array('name' => '5人目'), 43// '5' => array('name' => '6人目'), 44// '6' => array('name' => '7人目'), 45// '7' => array('name' => '8人目'), 46// ), 47// array( 48// '8' => array('name' => '9人目'), 49// ), 50// );

array_walk_recursive()を使った下記のサンプルコードでも上記と同じ結果が得られます。通常はforeach()を使ったほうがパフォーマンスが高いですが、メンテナンス性も考慮してどちらにするか決めてください。配列の要素数が大きくなるとパフォーマンスが非常に重要になります。

php

1// $records連想配列 2$records = array( 3 array('name' => '1人目'), 4 array('name' => '2人目'), 5 array('name' => '3人目'), 6 array('name' => '4人目'), 7 array('name' => '5人目'), 8 array('name' => '6人目'), 9 array('name' => '7人目'), 10 array('name' => '8人目'), 11 array('name' => '9人目'), 12); 13 14// $records配列を4つの要素で分割(インデックスはそのまま) 15$array = array_chunk($records, 4, true); 16 17for ($i=0; $i<count($array); $i++) { 18 echo "<div>\n"; 19 array_walk_recursive($array[$i], function ($value, $key) { 20 echo is_array($value) ?: "\t".$value."\n"; 21 }); 22 echo "</div>\n"; 23}

投稿2017/09/02 01:29

Tomak

総合スコア1652

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

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

退会済みユーザー

退会済みユーザー

2017/09/02 02:10

出力を再現しようとすると、array_reverse 2回使わないといけなくないですか?
Tomak

2017/09/02 02:53

順番に「1人目、2人目...」と表示するものとしていたのですが、「$records」配列の順番が違うということですよね。。。たしかにそうですね。 $recordsが「9人目、8人目」で出力を「<div>9人目</div><div>8人目...」とするのは、質問の文意からは解読不能でした。
guest

0

ベストアンサー

php

1foreach ($records as $record) {

から始まるループの中では、$record の値は一緒です。一緒でなかったら困りますよね。
ループ内の処理が終わって、次のループに入ったときに $record の中身が変わります。
何度 echo しても「9人目」になるのはそういう理由です。

次々にレコードにアクセスするには、foreach ($records as $record) のループはグルグル回しさなければなりません。数レコードずつまとめて表示するには、(1) レコードのループを回しながら、条件に応じてまとめるタグを出力する、(2) まとめて出力する用の多重配列にレコードを格納していって、あとでまとめて出力する、などの方法があると思います。

(1) のケースの例です。

php

1$records_per_div = 4; 2$count = 0; 3foreach ($records as $record) : 4 if ($count % $records_per_div == 0) : // 4 行ごとに div を始める 5 if ($count > 0) : // 最初以外は今までの div を閉じる 6 ?> 7</div> 8<?php endif; ?> 9<div> 10<?php endif; ?> 11<?php echo $record['name'] . "\n"; ?> 12<?php $count++; ?> 13<?php endforeach; ?> 14<?php if ($count > 0) : // 最後の div を閉じる ?> 15</div> 16<?php endif; ?>

(2) のケースです。div タグでまとめるものを section と名付けてあります。

php

1<?php 2$sections = array(); 3$records_per_div = 4; 4$index = 0; 5$section_no = 0; 6foreach ($records as $record) { 7 if ($index == 0) { 8 $section_no++; 9 $sections[$section_no] = array(); 10 } 11 $sections[$section_no][$index] = $record['name']; 12 $index++; 13 if ($index >= $records_per_div) $index = 0; 14} 15 16foreach ($sections as $section) : 17?> 18<div> 19<?php 20 foreach ($section as $name) { 21 echo $name."\n"; 22 } 23?> 24</div> 25<?php endforeach;

投稿2017/09/02 00:30

unau

総合スコア2468

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

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

退会済みユーザー

退会済みユーザー

2017/09/02 00:40

ありがとうございます!!説明も非常にわかりやすく、理解することが出来ました! また、自分の行っていた処理のどこが間違っていたのかも説明していただき、勉強になりました。 本当にありがとうございました!
guest

0

HTML の文法を確認するって意味では、Tomak さんのものをベースにするのが良いかも。

<div></div>の関係が分かりやすいです。 ```php <?php $records = [ [ 'name' => '9人目', 'age' => 20, ], [ 'name' => '8人目', 'age' => 21, ], [ 'name' => '7人目', 'age' => 22, ], [ 'name' => '6人目', 'age' => 23, ], [ 'name' => '5人目', 'age' => 24, ], [ 'name' => '4人目', 'age' => 25, ], [ 'name' => '3人目', 'age' => 26, ], [ 'name' => '2人目', 'age' => 27, ], [ 'name' => '1人目', 'age' => 28, ], ]; $records = array_reverse($records); $array = array_chunk($records, 4, true); $count = count($array); ?> <?php for ($i=$count-1; $i >= 0; --$i):?> <div> <?php $array[$i] = array_reverse($array[$i]);?> <?php foreach ($array[$i] as $record){ echo "\t".$record['name']."\n"; } ?> </div> <?php endfor ?> ```

投稿2017/09/02 02:32

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問