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

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

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

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

Q&A

解決済

4回答

2966閲覧

[PHP]配列のループ処理でグループ分けをしたい

uthio

総合スコア18

PHP

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

0グッド

0クリップ

投稿2019/06/19 08:11

編集2019/06/19 10:11

前提・実現したいこと

お世話になっております。
今回、以下の配列をその下にあるテーブルのように表示したく思っています。

php

1$data = array ( 2 0 => array ( 3 'no' => '89', 4 'title' => 'SAMPLE', 5 'status' => '保留', 6 'update' => '1900-01-01', 7 'importance' => '小', 8 'kind' => '11', 9 'group' => '3', 10 'flag' => '0', 11 ), 12 1 => array ( 13 'no' => '91', 14 'title' => 'hogehoge', 15 'status' => '開示', 16 'update' => '1900-01-01', 17 'importance' => '中', 18 'kind' => '13', 19 'group' => '3', 20 'flag' => '1', 21 ), 22 2 => array ( 23 'no' => '90', 24 'title' => 'テストタイトル', 25 'status' => '修正', 26 'update' => '1900-01-01', 27 'importance' => '大', 28 'kind' => '12', 29 'group' => '3', 30 'flag' => '0', 31 ), 32 3 => array ( 33 'no' => '92', 34 'title' => 'hogehoge', 35 'status' => '修正', 36 'update' => '1900-01-01', 37 'importance' => '小', 38 'kind' => '14', 39 'group' => '3', 40 'flag' => '1', 41 ), 42 4 => array ( 43 'no' => '93', 44 'title' => 'テストタイトル', 45 'status' => '開示', 46 'update' => '1900-01-01', 47 'importance' => '大', 48 'kind' => '15', 49 'group' => '3', 50 'flag' => '1', 51 ), 52 5 => array ( 53 'no' => '94', 54 'title' => 'SAMPLE', 55 'status' => '開示', 56 'update' => '1900-01-01', 57 'importance' => '小', 58 'kind' => '16', 59 'group' => '3', 60 'flag' => '1', 61 ), 62 6 => array ( 63 'no' => '95', 64 'title' => 'SAMPLE', 65 'status' => '保留', 66 'update' => '1900-01-01', 67 'importance' => '中', 68 'kind' => '17', 69 'group' => '3', 70 'flag' => '1', 71 ), 72 7 => array ( 73 'no' => NULL, 74 'title' => 'hogehoge', 75 'status' => '開示', 76 'update' => '1900-01-01', 77 'importance' => '中', 78 'kind' => '18', 79 'group' => '3', 80 'flag' => '1', 81 ) 82, )

■hogehoge
|no|title|status|update|importance|kind|group|flag|
|:--|:--:|--:|
|91|hogehoge|開示|1900-01-01|中|13|3|●|
|92|hogehoge|修正|1900-01-01|小|14|3|●|
||hogehoge|開示|1900-01-01|中|18|3|●|

■SAMPLE
|no|title|status|update|importance|kind|group|flag|
|:--|:--:|--:|
|89|SAMPLE|保留|1900-01-01|小|11|3||
|94|SAMPLE|開示|1900-01-01|小|16|3|●|
|95|SAMPLE|保留|1900-01-01|中|17|3|●|

■テストタイトル
|no|title|status|update|importance|kind|group|flag|
|:--|:--:|--:|
|90|テストタイトル|修正|1900-01-01|大|12|3||
|99|テストタイトル|開示|1900-01-01|大|15|3|●|

グループ化しないと実現できないとは思っているのですが、
テーブルが1つずつ羅列されるだけになってしまいます。

どのような方法がありますでしょうか。
解決策を与えていただけますと助かります。

試したこと

ひとまず途中まで記載したソースがこちらです。

php

1<?php foreach ($data as $list):?> 2<p><?=$list['title']?> 3<table border="2" cellpadding="2" cellspacing="0"> 4<?= $html_column1 ?>// ここは各カラム名が入っています 5 <?php if($list['status'] == "保留"):?>// ここは列の色を指定するための記述です(今回は関係なし) 6 <?php $color='#CCCCCC';?> 7 <?php elseif($list['status'] == "修正"):?> 8 <?php $color='#FFFF99';?> 9 <?php endif;?> 10 <tr bgcolor=<?=$color?>> 11 <td align="right" class="Bold1" width="40"> 12 <?=$list['no']?> 13 </td> 14 <td align="left" nowrap class="Bold1" width="400"> 15 <?=$list['title']?> 16 </td> 17 <td align="center" class="Bold1" width="100"> 18 <?=$list['status']?> 19 </td> 20 <td align="center" class="Bold1" width="100"> 21 <?=$list['Update']?> 22 </td> 23 <td align="center" class="Bold1" width="50"> 24 <?=$list['importance']?> 25 </td> 26 <td align="center" class="Bold1" width="50"> 27 <?=$list['kind']?> 28 </td> 29 <td align="center" class="Bold1" width="50"> 30 <?=$list['group']?> 31 </td> 32 <td><?php if ($list["flag"] == 1) { echo "●"; } else { echo ""; }?></td> 33 </tr> 34</table> 35<?php endforeach;?>

テーブル構造は以下の通りです。

SQL

1CREATE TABLE Test( 2no int(11) unsigned auto_increment, 3title varchar(200), 4status tinyint(4) DEFAULT 0, 5update date, 6importance tinyint(4) unsigned DEFAULT 0, 7kind tinyint(3) unsigned, 8group tinyint(4), 9flag tinyint(4), 10primary key (no) 11);

https://qiita.com/suin/items/c524cf84368332db426b
こちらを参考にグループ化することを考えましたが、
グループ化した後にどう記述すればいいか見当がつきませんでした。。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2019/06/19 08:18 編集

質問冒頭のArray?って、第三者が再現するためにわざわざ書き換えないといけないんよ。表組みして使用中のデータのサンプルを掲載しているけど、これも読み取ってデータ構造を再現するコードを別途書かなきゃいけない。回答者側に負担をかけない、ミニマルなコードでやり取りできないものだろうか。ハードルが高すぎるだろうか。第三者が再現しやすい内容になっていれば、どれ一丁もんでやるかとやる気になる質の回答者側の一人より。
date

2019/06/19 08:21

titleは固定で決まっているのですか? この質問はtitle別にテーブルにしたいということであってますか?
date

2019/06/19 08:24

データベースはSQLServerですか?
hentaiman

2019/06/19 08:30 編集

前回の質問のmtsさんの回答の通りにグループ化すれば済む話だと思いましたがそれをせずに今回のような形の配列にした理由は何でしょうか?使い方も書いてあったと思いますが
uthio

2019/06/19 08:33

>m6u様 気か効かず大変失礼いたしました。 すみません、そもそもどう記述すれば皆様に負担を掛けないのかすら今の私にはわかりませんでした。 以後、気を付けたいと思いますので、どうか「ここをこうして」とご指示だけでもいただけますと助かります。 >date様 コメントありがとうございます。 titleは固定でDBのtitleから流用になります。 データベースはMySQLでございます。 >hentaiman様 コメントありがとうございます。 前回ご回答いただいた点ではDBを更新するという答えに至ったので、そこからまた始めたのですが、グループ化するというのはどの部分になりますでしょうか。 私が理解できてないのだと思いますが、申し訳ありません、ご指摘いただけると助かります。
m.ts10806

2019/06/19 08:41

コードに利用する配列なのでしたらvar_dumpよりvar_exportで出力したものをご提示ください。
uthio

2019/06/19 08:55

>mts10806様 ご指摘ありがとうございます。 本当に申し訳ございません。修正いたしました。
m.ts10806

2019/06/19 08:57 編集

いえいえ。デバッグでvar_dump()はよく使いますが、var_export()は中々使う機会もなくて常用している人はあまりいないと思います。 ただ「これで再現確認がしやすくなるか」というところは一考してもらいたい、といったところですね。
m.ts10806

2019/06/19 09:04

あと、これ、テーブル定義も提示いただいた方がいいですね。 設計から見直すのであればテーブルの正規化から行ったほうが良さそうです。 このままだと結局ぐちゃぐちゃになります。 「取り出してからなんとかする」より「すぐにデータ表示できる形でSELECTする」方が圧倒的に良いです。 CREATE TABLE文とサンプルデータのINSERT文をご提示ください。
hentaiman

2019/06/19 09:14

見た感じtitleでグループ化して表示したいって事でしょ?titleでグループ化しましょ。 しかし何でグループ化したらいいかは人に聞く事ではなく、「〇〇でグループ化して表示したいけどどうやったら良い?」みたいな事を質問者が明言出来た時点で初めてどうしたいかが人に伝わるのよ。やりたい事を人に正しく伝えられるようになるとプログラムもどこを直せば対応出来るか分かるはず
uthio

2019/06/19 09:38

>mts10806様 ご丁寧にありがとうございます。 今回のDBですが、私にINSERTできる権限がない(基本SELECTしかできない)ので提示が出来ないのですが、CREATE TABLEはこちらのようです(一部改変しています)。 CREATE TABLE Test( no int(11) unsigned auto_increment, title varchar(200), status tinyint(4) DEFAULT 0, update date, importance tinyint(4) unsigned DEFAULT 0, kind tinyint(3) unsigned, group tinyint(4), flag tinyint(4), primary key (no) ); >hentaiman様 ご指摘ありがとうございます。 仰る通り今回はtitleでグループ化がしたいのが私の希望でした。 皆さまから頂いたご意見を踏まえ、同じtitlleのものを配列化して、それをループさせて表示する、というのが今の私が出せた答えです。 その方法はまだわかっていませんが…。 そもそもの知識が不足しているのを痛感しています。 丸投げのような質問になってしまって大変ご迷惑をお掛けしてすみません。
m.ts10806

2019/06/19 10:08

なるほど。やはりテーブルは1つでしたか。 質問本文に提示いただけますか?現状でも対応できないことはないんですが、やはりあまりよろしくはないです。
uthio

2019/06/19 10:16 編集

質問文に追記させていただきました。 テーブルを新しく作ることも現状では難しい状態です。。 タイトル名は同じPHP上で他でも使う(プルダウンで選択表示させるため)のでタイトル名だけ配列化したものは別の変数にも入れてます。 そして私の都合で大変申し訳ありません。 今、使っているPCがもうすぐ時間で落ちてしまいますので明日また対応させていただけますと幸いです。 本日は貴重なお時間を私に割いていただきありがとうございました。
guest

回答4

0

2個めの回答ですw

まず、DB からの取得ですが、以下を参考にしてみると良いです。
PDOフェッチパターン大全 - 3次元配列として取得

で、foreach ($data[TITLE] as $list)としてまわしてやると良いです。

投稿2019/06/19 12:48

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

uthio

2019/06/20 06:05

2回目のご回答ありがとうございました! せっかくいただいたのにすみません。 私が今、引きついでいる開発環境がPHP5.3でして、だいぶ古くから作られているもののようで、PDOによる接続をまだしてないため、PDO自体の知識不足があります。 ただ頂いたものを把握するのに以下の記事など見つけましたので、これらと合わせて勉強させていただきたく思います。 https://qiita.com/mpyw/items/b00b72c5c95aac573b71 https://qiita.com/tabo_purify/items/d1166236f3b03c7be60d 要件次第では使う時が必ず来ると思いますので、その際にはここを思い出してやってみます。 ありがとうございました。
退会済みユーザー

退会済みユーザー

2019/06/20 07:47

5.3 はかなりまずい状況ですね。。。^^; 早めにバージョンアップの判断をされることをオススメします。
uthio

2019/06/20 07:54

とても古くからのお客様で、データも膨大になりすぎてタイミングを逃し続けているんだと思います。。 いつか、バージョンアップする時が来ると思いますので、その時のために準備します。
guest

0

title でテーブルを分離する表と理解しました。

title が固定なのであれば、title の値で配列を分離して、表を書けば良いです。
例で言えば、$hogehoge, $sample, $test_title を作成して、そこに要素を分配して下さい。

あとは、foreach で表を作ればよいかと。

<tr> を作る部分は適当に関数として切り出して、配列を与えるようにすればスッキリしますが、テンプレートとして可読性を犠牲にする必要もないので、べた書きでも良いと思います。

投稿2019/06/19 08:22

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2019/06/19 08:41

追記/修正のやり取り見てると、DB から取り出すときに配列の構造を調整しちゃったほうが良さそうね^^;
m.ts10806

2019/06/19 08:58

前の回答で「表示する形を想定してSELECTするといいよ」という旨のヒントは出したんですけどね・・
uthio

2019/06/19 09:01

>te2ji様 ご回答ありがとうございます。 すみません、私の拙い質問のせいで皆様にお手数をかけてしまって、頭が全然追い付いてなくて返答できておりませんでした。。 いただいたお答え、参考にさせていただき、皆様のご意見を受けて再度実装してみます。
guest

0

ベストアンサー

制限事項を整理しますと下記ですね。

  • データは自分では投入できない。アクセス(SELECT)のみ
  • 新しいテーブルは自分では作れない

とりあえず、データ取得時にtitleでORDER BYかけてください。昇順でも降順でも。
あとできればimportanceでもORDER BYかけたほうがいいかもしれませんね。そこは要件次第で。
あまり全角文字列でのORDER BYって良くないんですが、今回は制限事項がかなり厳しいので仕方ありません。

そうすると一応、見やすくはなります。

ただしtitleでORDER BYかけるので、もしかしたら同じ順番にならなくなるかもしれません。そこは仕方ないです。
※本来ならtitleもimportanceもstatusも外に出したほうが良いですし、group内の順番を制御するカラムも欲しいところです。

あとは、titleが変わるタイミングで<table>を切って次のtitleを出すようにループで調整してください。

※簡易例。未検証です。

php

1$pre_title = ""; 2 3$listHtml = ""; 4foreach($dataList as $row){ 5 if(!empty($pre_title) && $row["title"] != $pre_title){ 6 echo $row["title"]; 7 echo <<<TABLE 8<table> 9{$listHtml} 10</table> 11TABLE; 12 $listHtml = ""; 13 } 14 $listHtml .= <<<RECORD 15<tr> 16 <td>{$list['no']}</td> 17 <td>{$list['status']}</td> 18 <td>{$list['Update']}</td> 19</tr> 20RECORD; 21 $pre_title = $row["title"] ; 22} 23

あと、蛇足ですが出力処理時にHTMLエスケープは入れてください(今回は省きました)

投稿2019/06/19 12:30

m.ts10806

総合スコア80850

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

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

uthio

2019/06/20 04:20

ご回答まで記載いただきありがとうございました。 今、いただいたものを元に調整しているのですが、pre_titleへの代入が最後にあるため、質問文でいう■hogehogeが省略されて、一つずつズレてしまう状況になっています。 (■SAMPLEにhogehogeのテーブル情報が入り、■テストタイトルにSAMPLEのテーブル情報が入っている状態です) 先にpre_titleにタイトル入れてみたりifの条件を変えたりは上手くいかず、初回はスキップするなど考えましたがそれだと後でもう一度、別で記述しなければならないと思い辞めました。 何度も聞いてばかりで申し訳ないです。 ここの解決策はありますでしょうか?
m.ts10806

2019/06/20 04:27 編集

あ、そうですね それなら echo $row["title"]; を echo $pre_title; にすればうまくいくと思います。 ただ・・・。 最後のレコードは出力されないので、そこは改善してみてください。 foreachのループの特性を理解していればできると思います
uthio

2019/06/20 06:18

お陰様でようやく再現したいことが出来ました…! アドバイスいただき、foreachは要素数しかループしないということを思い出して、結局for文で回数指定してループ回すことにしました。 今回はとても自分の知識不足も痛感しましたが、mts10806様をはじめとした皆さまにとても助けられました。 大変、感謝いたします。 DB設計からの大切さや知らない関数など勉強させていただきました。 重ねてお礼申し上げます。
m.ts10806

2019/06/20 06:21

そうですね。 まずは「モック(試作品、静的表示)」でレイアウトサンプルを作ってみると良いです。 「デザインは機能」ともいわれるくらいで、デザインが決まらないことには機能も決まらないし 機能が決まらないことにはデータも決まりません。 後から何とかするのって本当にしんどい思いをすることになります(私なら全編作り変えます) ひとえに「設計」といってもそんなに構える必要はなく とりあえず画面に必要な情報を配置した図を作って、「ここを押したらこういう処理をする」みたいな形のものをメモ書きにするだけでも良いんです。 何もない状態で作っていくと必ず不整合が出るので。 メモ書きでもちょっとあると全然違ってきます。 もちろん実装していくうえで「おかしいな」と思うところはあるのですが、 そこは設計に立ち返って調整してまた実装すれば良いだけの話です。 trial and error ですね。
uthio

2019/06/20 06:33

ご丁寧にアドバイスまでありがとうございます。 私は今、駆け出しでして最初から設計することはなく、基本的には既存のものの改修を担当することが多く、やりながら覚えるというスタンスで現場に投入されている状態です。 知識も大事な基礎が抜けており、言葉が悪いですが歯抜けが多いと認識してます。 もちろん、先輩方のコードを見て都度意味を調べて、といった形で勉強させていただいているのですが、まだまだですね。 メモはよく書くクセをつけてます。 今は指示を見て、単純にやりたいことを書いて、実現のためにどうするか、みたいなものですが。。 空いた時間でレイアウトサンプルなど挑戦してみます。 いつか自分で設計する時にはmts10806様のお言葉を思い出します。
m.ts10806

2019/06/20 06:38

今の段階から意識しておくと既存改修でも製造でも役に立つと思いますよ。 「考える」ことは自身を成長させますから。 技術的なところで言うとPHPマニュアルを辞書がわりに使えるようになることです。 あと今の環境が5.3とのことですが、レガシーシステムのメンテンナンスやちょっとした改修を除いて 現場で出会うことはありませんので、PHP7.1以上を前提に学習してください。 自身のローカルに別途入れて合間に遊ぶだけでもだいぶ違うと思います。
uthio

2019/06/20 07:48

まずは考える、メモを取るですね。 それはどんな作業の時でも意識していこうと思います。 やはり5.3はもう殆どないんですね。 今の案件が終わったら次どうなるか分からないので、仰る通り前もって7.1以上に手を付けておこうと思います。 ご配慮までいただきありがとうございます。
uthio

2019/06/20 08:08

終わった後にすみません…。 再度確認していたところ、最初のテーブルの1行目(質問本文だと「91 hogehoge」です)だけ消えていまして、、スルーされる原因はお分かりでしょうか…?
m.ts10806

2019/06/20 08:18

いったん状況まとめて別質問にされたほうが良いかもしれません。
uthio

2019/06/20 08:18

あ、すみません、これは私のミスです。 一旦忘れていただいて大丈夫です。
m.ts10806

2019/06/20 08:22

>まずは考える、メモを取るですね。 そういえばどこにも「メモを取る」ということは書いてませんが・・・ あくまで「機能をメモ書きにする」ということですよ。「ここはこういう処理をする」と文章で書くということです。それがちょっとした設計代わりになるという意味です。 それを形式化したのがフローチャートであり実際の設計書です。
uthio

2019/06/20 08:44

あ、その認識でおりました。 普段もその感じでエクセルなどに図におこしたりしてます。 日本語が下手でした、、失礼しました。
guest

0

こんな感じでしょうか?

PHP

1<?PHP 2$data =[ 3 ["no"=>89,"title"=>"SAMPLE","status"=>"保留","update"=>"1900-01-01","importance"=>"小","kind"=>11,"group"=>3,"flag"=>0,], 4 ["no"=>91,"title"=>"hogehoge","status"=>"開示","update"=>"1900-01-01","importance"=>"中","kind"=>13,"group"=>3,"flag"=>1,], 5 ["no"=>90,"title"=>"テストタイトル","status"=>"修正","update"=>"1900-01-01","importance"=>"大","kind"=>12,"group"=>3,"flag"=>0,], 6 ["no"=>92,"title"=>"hogehoge","status"=>"修正","update"=>"1900-01-01","importance"=>"小","kind"=>14,"group"=>3,"flag"=>1,], 7 ["no"=>93,"title"=>"テストタイトル","status"=>"開示","update"=>"1900-01-01","importance"=>"大","kind"=>15,"group"=>3,"flag"=>1,], 8 ["no"=>94,"title"=>"SAMPLE","status"=>"開示","update"=>"1900-01-01","importance"=>"小","kind"=>16,"group"=>3,"flag"=>1,], 9 ["no"=>95,"title"=>"SAMPLE","status"=>"保留","update"=>"1900-01-01","importance"=>"中","kind"=>17,"group"=>3,"flag"=>1,], 10 ["no"=>NULL,"title"=>"hogehoge","status"=>"開示","update"=>"1900-01-01","importance"=>"中","kind"=>18,"group"=>3,"flag"=>1,], 11 ]; 12$titles=array_unique(array_map(function($x){ 13 return $x["title"]; 14},$data)); 15 16foreach($titles as $title){ 17 print "<table border>\n"; 18 print "<caption>$title</caption>\n"; 19 print "<thead>\n"; 20 print "<tr>\n"; 21 foreach(array_keys($data[0]) as $val){ 22 print "<th>$val</th>\n"; 23 } 24 print "</tr>\n"; 25 print "</thead>\n"; 26 print "<tbody>\n"; 27 foreach(array_filter($data,function($x) use($title){ 28 return $x["title"]==$title; 29 }) as $vals){ 30 print "<tr>\n"; 31 foreach($vals as $val){ 32 print "<td>$val</td>\n"; 33 } 34 print "</tr>\n"; 35 } 36 print "</tbody>\n"; 37 print "</table>\n"; 38} 39

投稿2019/06/19 08:52

yambejp

総合スコア114839

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

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

uthio

2019/06/19 09:40

>yambejp様 ご回答ありがとうございます。 せっかく頂いたのに返答が遅くなり失礼いたしました。 今、皆様から色んなご指摘やご意見を頂戴していて、私が追い付けていないせいなのですが、後ほど必ず参考にさせていただきます。 その後で改めてコメントお送りします。
uthio

2019/06/20 06:21

ご回答の件、改めて試させていただきました。 いただいた記述でも調整すれば思っていたようなことが再現できそうなもので、理解できました。 今回はmts10806様に長い時間、ヘルプしていただいたのでmts10806様のお答えを使わせていただきましたが、yambejp様からの回答も覚えておきます。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問