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

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

ただいまの
回答率

87.59%

【PHP】配列のkeyとValueでテーブルを作成したい

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 963

score 13

お世話になっております。
PHPで、以下の配列を

$nArray = array(
    見出し1 => コンテンツ1,
    見出し2 => コンテンツ2,
    見出し3 => コンテンツ3,
    見出し4 => コンテンツ4
)

下記のような形でテーブルとして出したいのですが、
どのようなコードになりますでしょうか。

イメージ説明

現状、以下のような形で単純にテーブルにkey値と、$value値を出力されることはできました。

<table>
    <?php foreach ($nArray as $key => $value): ?>
        <tr>
            <th><?php echo $key;?></th>
            <td><?php echo $value;?></td>
        </tr>
    <?php endforeach; ?>
</table>


key値と$value値をtrの中に複数(2つづつ)出したいのですが、ループの仕方が不明で…。
質問下手くそで申し訳ありません。

お手数をお掛け致しますがご教授頂けると助かります。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2019/02/26 20:21

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

  • 退会済みユーザー

    退会済みユーザー

    2019/02/26 20:22

    どのあたりがわからないのかを質問文に記載していただけますか?
    既にご自分で調べた内容や試したことがあると思いますので、質問文への追記をお願いします。

    キャンセル

回答 5

+4

こういう対応する場合、私は、まずは静的HTMLでゴールを作ってそれを目指していきます。
たぶんこんな感じ。

<table>
    <tr>
        <th>1</th>
        <td>a</td>
        <th>2</th>
        <td>b</td>
    </tr>
    <tr>
        <th>3</th>
        <td>c</td>
        <th>4</th>
        <td>d</td>
    </tr>
    <tr>
        <th>5</th>
        <td>e</td>
        <th></th>
        <td></td>
    </tr>
</table>

ブラウザ表示結果
イメージ説明

最後、奇数になると埋める必要があると思ったので空の組みを1つ出しています。

ここで法則を見つけ出します。th-tdの組が2回あったあとにtrが閉められています。
それを実現すればいいわけですね。
「ループの回数が偶数であればtr閉め」となりますが、PHPに限らずに使われるのが余りを出す%を使った方法です。
「偶数」の場合は対象の値を%2とします。

ミニマムコード:

for($i=0;$i<10;$i++){
    if($i%2===1){
        echo $i;
    }
}
//13579

これを応用して、いきます。

第1段階

<table>
    <?php 
    $i=0;
    $th_tr_group = "";
    foreach ($nArray as $key => $value){
        $th_tr_group .="
        <th>{$key}</th>
        <td>{$value}</td>\n";
        if($i%2===1){
            echo "<tr>{$th_tr_group}</tr>\n";
            $th_tr_group = "";
        }
        $i++;
    }
?>
</table>  

実は、
このコードには1点問題があり、「奇数個データがあったときにそこが出力されない」という問題があります。
偶数のときにしかechoしていないためですね。
ここを「余ってたら出す」ようにする必要があります。

foreachなどループの関数には特性があり、「明示的にその変数をOFFにしない限り最後の値が残っている」となります。

ので、第2段階としては下記

<table>
    <?php 
    $i=0;
    $th_tr_group = "";
    foreach ($nArray as $key => $value){
        $th_tr_group .="
        <th>{$key}</th>
        <td>{$value}</td>\n";
        if($i%2===1){
            echo "<tr>{$th_tr_group}</tr>\n";
            $th_tr_group = "";
        }
        $i++;
    }
echo "<tr>
    <th>{$key}</th>
    <td>{$value}</td>
    <th></th>
    <td></td>
</tr>";
?>
</table> 

ブラウザで見たとき
イメージ説明
※テスト用の配列を0開始で作ってる関係で0が最初に来ています。

ただ、これにも問題があります。
「2じゃなくて3とかにしたい」となった場合に、書き換えが必要となります。

もう少しそこを汎用的に作ります。
先ほどの「明示的にその変数をOFFにしない限り最後の値が残っている」というのと
「tr閉じられないときは$th_tr_groupがリセットされていない」というのを利用します。
あとは「データ何個で折り返すか」変数を作り、上記までの対応を利用し、
その変数の数値をいじりながら出力結果を見て調整した結果、下記のような感じです。

<?php
$row_point = 2;
?>
<table>
    <?php

    $i=0;
    $th_tr_group = "";
    foreach ($nArray as $key => $value){
        $th_tr_group .="
        <th>{$key}</th>
        <td>{$value}</td>\n";
        if($i%$row_point>=($row_point-1)){
            echo "<tr>{$th_tr_group}</tr>\n";
            $th_tr_group = "";
        }
        $i++;
    }
    if($i%$row_point>=1){
        for($r=0;$r<($i%$row_point);$i++){//余りを空で埋める
            $th_tr_group .="
            <th></th>
            <td></td>\n";
        }
        echo "<tr>{$th_tr_group}</tr>\n";
    }
?>
</table>

※結果は同じ。

$row_pointの値を変えるだけで1行の個数が変化し、残りを空で埋めるようになっています。
ちなみに、2,3は割と簡単ですが、4以上の調整に結構時間かかります。

$row_pointを3にしたとき(HTML出力結果)

<table>
    <tr>
        <th>0</th>
        <td>a</td>

        <th>1</th>
        <td>b</td>

        <th>2</th>
        <td>c</td>
</tr>
<tr>
        <th>3</th>
        <td>d</td>

        <th>4</th>
        <td>e</td>

            <th></th>
            <td></td>
</tr>
</table>

4にしたとき

<table>
    <tr>
        <th>0</th>
        <td>a</td>

        <th>1</th>
        <td>b</td>

        <th>2</th>
        <td>c</td>

        <th>3</th>
        <td>d</td>
</tr>
<tr>
        <th>4</th>
        <td>e</td>

            <th></th>
            <td></td>

            <th></th>
            <td></td>

            <th></th>
            <td></td>
</tr>
</table>


5にしたとき

<table>
    <tr>
        <th>0</th>
        <td>a</td>

        <th>1</th>
        <td>b</td>

        <th>2</th>
        <td>c</td>

        <th>3</th>
        <td>d</td>

        <th>4</th>
        <td>e</td>
</tr>
</table>


6にしたとき

<table>
    <tr>
        <th>0</th>
        <td>a</td>

        <th>1</th>
        <td>b</td>

        <th>2</th>
        <td>c</td>

        <th>3</th>
        <td>d</td>

        <th>4</th>
        <td>e</td>

            <th></th>
            <td></td>
</tr>
</table>

参考まで。

※HTMLコードのインデントなどはとりあえず無視で、結果出力だけあわせました。
インデントあわせたい場合はご自身で調整してください。


蛇足:

テストでたくさんデータを作ってみる。

$nArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
$row_point = 6;


イメージ説明

$nArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25];
$row_point = 2;


イメージ説明
同じデータで$row_point = 3;
イメージ説明
同じデータで$row_point = 5;
イメージ説明

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/27 09:24

    mts10806さん
    本当にご丁寧にご回答ありがとうございます。奇数時の処理も含めてご返答頂いた内容を元に解析させて頂き処理に反映したいと思います。

    キャンセル

  • 2019/02/27 09:53

    私の回答はあくまでロジックと思ってください。
    何かを実現するときの検証のしかた。
    ミニマムコードで試して徐々に当てはめて徐々に調整していく。
    実は「その変数の数値をいじりながら出力結果を見て調整した結果」のコードが一番時間がかかってます。
    そのあたりまで伝えられればいいのですが、回答欄では伝えきれないものとしてコードを提示するだけに留めました。
    しかしながら、色々なデータを投入してきちんと想定通り動くかの確認は必須なので、その上で不都合な結果が出れば調整していく、という感じですね。(この過程が楽しめるようになればいい技術者になれます)

    キャンセル

  • 2019/02/27 10:26

    ちなみに「処理に反映する」とおっしゃっていますが、既にご自身で「データを処理で扱いやすい形態にする」方向に舵を切られているので、私の回答を取り込むのはかえってグチャグチャになります。データ側で対応するようにしてください。半端は良くないです。
    あくまで質問の状態のデータを処理でやった場合のやり方です。

    キャンセル

check解決した方法

0

普通の配列では無理なので、データの生成の仕方を以下に変えました。

$nArray = array(
    見出し1 => コンテンツ1,
    見出し2 => コンテンツ2,
    見出し3 => コンテンツ3,
    見出し4 => コンテンツ4
)

だったものを

$nArray = array(
   array(
    見出し1 => コンテンツ1,
    見出し2 => コンテンツ2,
    ),
   array(
    見出し3 => コンテンツ3,
    見出し4 => コンテンツ4,
    ),
)

としました。
内部的な話をすると、カスタムフィールドから値をとってきて
配列としていました。
単純な配列では無理でしたので、連想配列?にして、以下のような形で吐き出させさせました。

<?php foreach($nArray as $row): ?>
    <tr>
    <?php foreach($row as $key => $cel): ?>
        <td><?= $key ?></td>
        <td><?= $cel ?></td>
    <?php endforeach; ?>
    </tr>
<?php endforeach; ?>

今回は大変わかりにくい質問ですいませんでした。自己解決しましたので記載しておきます。
もっとスマートなやり方をご存知の方いらっしゃいましたらご教示頂ければと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/26 21:54

    確かに「出力しやすい形にデータをかえる」というのはあると思います。
    データがデータベースにある場合、SELECTするときにHTML出力想定結果に近い形のデータを作っておく、とかですね。
    ひとまず「並列的なデータだった場合の対応」で回答してみましたので、参考にしてみてください。

    キャンセル

  • 2019/02/26 21:55

    ただ、それだと2列出すとして偶数ならいいですが奇数の場合は空の配列が作る必要があるので、そこをコスト高いと考えるかどうかが争点ですね。

    キャンセル

  • 2019/02/27 09:16

    mts10806さん
    ご解答ありがとうございます!
    今回は仕様でこちら側で出力項目数をハンドルリングする事ができ、吐き出される項目数として『偶数である』という縛りをつけてしまいました。ただ、これではご指摘のある通り奇数の場合にコストが高くあまり汎用性ではない処理なので頂いたご返答を元を自分なりに解析して処理に反映したいと思います。

    キャンセル

0

table タグで並べるデータでは無いような気がします。
css で並べてあげるのが適切かと。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

chunkして最後の要素のあまりをnullで埋めればいいのでは?

$cols=3;
$a = [
  "見出し1" => "コンテンツ1",
  "見出し2" => "コンテンツ2",
  "見出し3" => "コンテンツ3",
  "見出し4" => "コンテンツ4",
  "見出し5" => "コンテンツ5",
];
$b=array_chunk($a,$cols);
$c=array_fill(0,$cols-count($b[count($b)-1]),NULL);
$b[count($b)-1]=array_merge($b[count($b)-1],$c);

print_r($b);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

-2

echo "<table>";
foreach($nArray as $key  => $val)
{
  echo "<tr><td>" . $key . "</td><td>" . $val . "</td></tr>";
}
echo "</table>";

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/28 14:38

    確かにそうですね。そこは失礼しました。
    ただ、画像は最初からあがっているようなので、
    提示の仕方では画像の通りにはならないと思います。

    キャンセル

  • 2019/02/28 14:41

    mts10806さん
    > 提示の仕方では画像の通りにはならないと思います。

    はい、そうですね。
    質問文には具体的なコードが一切書かれていなかったので、そもそも配列をforeachで回す方法はわからないのではないかと思っての回答でした。

    キャンセル

  • 2019/02/28 14:45

    まあ、風呂に入りながら、スマホからポチポチ打ったコードなので、今確かめると全角スペースが混ざってしまっているエラーコードですから、悪いコードなのは確かですね。

    キャンセル

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

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る