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

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

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

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

Q&A

解決済

3回答

2089閲覧

PHP 登録状況で変わる選択肢の状態にあわせてforeach?などで書き出したい

mi_

総合スコア80

PHP

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

0グッド

1クリップ

投稿2017/01/16 06:58

編集2017/01/16 09:56

たびたびお世話になっています。
アンケートに関するPHPのページを作成しようと思っています。

1.行いたいことは、アンケートの本文と、選択枝のMySQLへの格納。
2.アンケート画面で、データベースから抽出して、選択肢を表示
3.チェックボックスやラジオボタンの状態を、DBへ書き込み

この中の2をどのようにできるかによって1の画面を作りたいと思っています。

下記のような配列のテスト画面を作りました。

PHP

1//test.php 2<?php 3$survey= array( 4 "sur1"=> array("紹介", 5 "看板", 6 "チラシ", 7 8 "フリーペーパー" => array ("雑誌A", 9 "雑誌B", 10 "雑誌C", 11 "雑誌D"), 12 13 "ネット" => array ("ホームページ", 14 "EPARK", 15 "エキテン", 16 "LINE", 17 "Facebook", 18 "Instagram", 19 "その他") 20 ), 21 22 "sur2"=> array("A市","B市","D市","E郡","その他のA県内","B県","その他の県"), 23 "sur3"=> array("車で5分以内","車で10分以内","車で20分以内","車で30分以内","それ以上") 24 25); 26 27 28var_dump($survey); 29 30print '<br><br><br>'; 31 32var_dump($survey['sur1']); 33 34print '<br><br><br>'; 35 36var_dump($survey['sur1']['フリーペーパー']); 37 38print '<br><br><br>'; 39 40 41//試してみてうまくいかなかったコードです。 42//このようにすれば、フリーペーパーの中身は表示されますが、sur1やフリーペーパーをあらかじめ入力するのではなく、変数で入れたいのですが、その変数の取得方法が分かりませんでした。 43foreach( $survey['sur1']['フリーペーパー'] as $value ){ 44 echo $value."<br>"; 45} 46 47 48?>

上記のPHPに対してブラウザに表示された内容のコピペです。


array(3) { ["sur1"]=> array(5) { [0]=> string(6) "紹介" [1]=> string(6) "看板" [2]=> string(9) "チラシ" ["フリーペーパー"]=> array(4) { [0]=> string(7) "雑誌A" [1]=> string(7) "雑誌B" [2]=> string(7) "雑誌C" [3]=> string(7) "雑誌D" } ["ネット"]=> array(7) { [0]=> string(18) "ホームページ" [1]=> string(5) "EPARK" [2]=> string(12) "エキテン" [3]=> string(4) "LINE" [4]=> string(8) "Facebook" [5]=> string(9) "Instagram" [6]=> string(9) "その他" } } ["sur2"]=> array(7) { [0]=> string(4) "A市" [1]=> string(4) "B市" [2]=> string(4) "D市" [3]=> string(4) "E郡" [4]=> string(19) "その他のA県内" [5]=> string(4) "B県" [6]=> string(15) "その他の県" } ["sur3"]=> array(5) { [0]=> string(16) "車で5分以内" [1]=> string(17) "車で10分以内" [2]=> string(17) "車で20分以内" [3]=> string(17) "車で30分以内" [4]=> string(12) "それ以上" } } array(5) { [0]=> string(6) "紹介" [1]=> string(6) "看板" [2]=> string(9) "チラシ" ["フリーペーパー"]=> array(4) { [0]=> string(7) "雑誌A" [1]=> string(7) "雑誌B" [2]=> string(7) "雑誌C" [3]=> string(7) "雑誌D" } ["ネット"]=> array(7) { [0]=> string(18) "ホームページ" [1]=> string(5) "EPARK" [2]=> string(12) "エキテン" [3]=> string(4) "LINE" [4]=> string(8) "Facebook" [5]=> string(9) "Instagram" [6]=> string(9) "その他" } } array(4) { [0]=> string(7) "雑誌A" [1]=> string(7) "雑誌B" [2]=> string(7) "雑誌C" [3]=> string(7) "雑誌D" } 雑誌A 雑誌B 雑誌C 雑誌D

ブラウザのソースのコピペです。

array(3) { ["sur1"]=> array(5) { [0]=> string(6) "紹介" [1]=> string(6) "看板" [2]=> string(9) "チラシ" ["フリーペーパー"]=> array(4) { [0]=> string(7) "雑誌A" [1]=> string(7) "雑誌B" [2]=> string(7) "雑誌C" [3]=> string(7) "雑誌D" } ["ネット"]=> array(7) { [0]=> string(18) "ホームページ" [1]=> string(5) "EPARK" [2]=> string(12) "エキテン" [3]=> string(4) "LINE" [4]=> string(8) "Facebook" [5]=> string(9) "Instagram" [6]=> string(9) "その他" } } ["sur2"]=> array(7) { [0]=> string(4) "A市" [1]=> string(4) "B市" [2]=> string(4) "D市" [3]=> string(4) "E郡" [4]=> string(19) "その他のA県内" [5]=> string(4) "B県" [6]=> string(15) "その他の県" } ["sur3"]=> array(5) { [0]=> string(16) "車で5分以内" [1]=> string(17) "車で10分以内" [2]=> string(17) "車で20分以内" [3]=> string(17) "車で30分以内" [4]=> string(12) "それ以上" } } <br><br><br>array(5) { [0]=> string(6) "紹介" [1]=> string(6) "看板" [2]=> string(9) "チラシ" ["フリーペーパー"]=> array(4) { [0]=> string(7) "雑誌A" [1]=> string(7) "雑誌B" [2]=> string(7) "雑誌C" [3]=> string(7) "雑誌D" } ["ネット"]=> array(7) { [0]=> string(18) "ホームページ" [1]=> string(5) "EPARK" [2]=> string(12) "エキテン" [3]=> string(4) "LINE" [4]=> string(8) "Facebook" [5]=> string(9) "Instagram" [6]=> string(9) "その他" } } <br><br><br>array(4) { [0]=> string(7) "雑誌A" [1]=> string(7) "雑誌B" [2]=> string(7) "雑誌C" [3]=> string(7) "雑誌D" } <br><br><br><br><br><br>雑誌A<br>雑誌B<br>雑誌C<br>雑誌D<br>

上記を元に、ブラウザに下記のように出力したいと思っていますが、上記のような配列をもとに、選択肢の数だけ出力するのは可能でしょうか?


アンケート
ここにアンケート本文

〇紹介 〇看板 〇チラシ フリーペーパー【 〇雑誌A 〇雑誌B 〇雑誌C 〇雑誌D 】 ネット 【 〇ホームページ 〇EPARK 〇エキテン 〇LINE 〇Facebook 〇Instagram 〇その他 】

ここにアンケート本文
〇A市 〇B市 〇D市 〇E郡 〇その他のA県内 〇B県 〇その他の県

ここにアンケート本文
〇車で5分以内 〇車で10分以内 〇車で20分以内 〇車で30分以内 〇それ以上


上記のように書き出すことが可能であれば、この選択肢を登録する画面や、DBへの書き込み、DBからの書き出しを検討したいと思っています。難解すぎたり、非効率であれば、別の方法を使いたいとも思っていますが、DBへの負荷?などを考えると上記のようにした方がいいような気がしています。
foreachなどをいくつか試しましたが、うまくいきませんでした。

実際には、登録状況で変わる選択肢の状態にあわせてforeachで取り出したいのですが、なかなかうまくいきません。上記のように、配列と配列じゃないものが混ざっているのはNGでしょうか?上記のような配列を作るのは、問題があるのか、また書き出し方(チェックボックスやHTMLタグは不要ですが、条件分岐やループの回し方を知りたいです)等、お知恵をお借りできればと思っています。

お手数おかけしますが、よろしくお願いします。

追記
あやふやな質問で申し訳ありません。
具体的に、
・選択肢の数だけループを回したいと思っています。
・配列の中身が、配列だったり連想配列だったりしていますが、その状況にあわせたループの作り方がわかりません。
・配列の中身を下記のようなループで表現したいのですが、どのようにしたらいいかわかりませんでした。

大外のループ(sur1,sur2,sur3などがあるだけ回す)
外のループ sur1の中の紹介、看板、チラシなどを中身のあるだけ回す。
フリーペーパー部分のような、配列を持った部分をさらにループで回す。
外のループ sur2の中身分回す
外のループ sur3の中身分回す

のようなイメージをしています。

sur1,sur2,フリーペーパーなどを直接記入せず、変数で処理できればと思います。


こちらのルール違反かもしれませんが、ご回答いただいたことをもとにまずこのようにしてみました。

<?php $survey_q = array ( "sur1" => "当店をお知りになったきっかけは何ですか?", "sur2" => "お住まいの市町村はどちらですか?", "sur3" => "当店におこしいただくまでの時間はどのくらいですか?", ); $survey= array( "sur1"=> array("紹介", "看板", "チラシ", "フリーペーパー" => array ("雑誌A", "雑誌B", "雑誌C", "雑誌D"), "ネット" => array ("ホームページ", "EPARK", "エキテン", "LINE", "Facebook", "Instagram", "その他") ), "sur2"=> array("A市","B市","D市","E郡","その他のA県内","B県","その他の県"), "sur3"=> array("車で5分以内","車で10分以内","車で20分以内","車で30分以内","それ以上") ); foreach ($survey_q as $key => $value){ $select_key = $key; print $value; print '<br><br>'; //print $select_key; // foreach($survey[$select_key] as $key => $choiceData1) { // 複数選択肢か判定 if(is_array($choiceData1)) { // 複数選択肢の項目表示 echo $key . PHP_EOL; // 複数選択肢表示 foreach($choiceData1 as $choiceData2) { echo $choiceData2 . PHP_EOL; } } else { // sur1,2,3直下の選択肢表示 echo $choiceData1 . PHP_EOL; } } print '<br><br><br>'; } print '<br><br><br>'; ?>

結果このように表示されました。これをもとに少しずつ目的の状態まで変えていきたいと思います。ご回答いただいた皆様、本当にありがとうございました。

当店をお知りになったきっかけは何ですか? 紹介 看板 チラシ フリーペーパー 雑誌A 雑誌B 雑誌C 雑誌D ネット ホームページ EPARK エキテン LINE Facebook Instagram その他 お住まいの市町村はどちらですか? A市 B市 D市 E郡 その他のA県内 B県 その他の県 当店におこしいただくまでの時間はどのくらいですか? 車で5分以内 車で10分以内 車で20分以内 車で30分以内 それ以上

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

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

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

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

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

kei344

2017/01/16 07:03

質問文の「ブラウザに表示された内容」もコードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「<code>」ボタンを押すとコードブロックになります。
mi_

2017/01/16 07:09

見ていただいてありがとうございます。コードブロックで囲ませていただきました。
kei344

2017/01/16 07:15

「うまくいきませんでした」とありますが、ご自信の試されたコードも追記されてはいかがでしょうか。
mi_

2017/01/16 07:30

うまくいかなかったコードを追記しました。
zico_teratail

2017/01/16 07:36

何がどう「うまくいかなかった」のですか? 最終的にどういう形にしたいのですか? 見る限り、var_dumpで必要な中身を表示できているので「うまくいっている」と思いますが。
guest

回答3

0

ベストアンサー

foreachでループさせて、値が配列かテキストか判定してください。
参考:is_array

また、foreachはkey、valueを扱えます。
複数選択肢の項目(フリーペーパー、ネット)表示にはこちらを利用してください。
参考:foreach

しかし、ご提示頂いた配列のデータでは、以下のサンプル通りループがネストし、後々バグの温床となりそうです。
扱いやすいようにフォーマットしたほうが良いかと思います。

php

1// $surveyのforeach 2foreach($survey as $surveyData) { 3 // sur1,2,3のforeach 4 foreach($surveyData as $key => $choiceData1) { 5 // 複数選択肢か判定 6 if(is_array($choiceData1)) { 7 // 複数選択肢の項目表示 8 echo $key . PHP_EOL; 9 // 複数選択肢表示 10 foreach($choiceData1 as $choiceData2) { 11 echo $choiceData2 . PHP_EOL; 12 } 13 } 14 else { 15 // sur1,2,3直下の選択肢表示 16 echo $choiceData1 . PHP_EOL; 17 } 18 } 19} 20

投稿2017/01/16 07:51

mri0815

総合スコア429

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

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

mi_

2017/01/16 07:58

回答ありがとうございました。 この複数選択しかどうかの判定ができずにいました。 大変勉強になりました。 初心者にはループがネストするのがうまいやり方というイメージでいましたが、見にくい?以外になにか問題がありそうでしょうか? 別のフォーマットに変えるというご提案ですが、本当はもっと上手な構造があるのでしょうか? 質問ばかりですみません。
mri0815

2017/01/16 08:15

確認いただきありがとうございます。 今回のように使用するデータを単純に配列に格納した場合、知っている人が見る分には良いかもしれませんが、 あとで別なコーダーが見た際に何に使用しているデータか分かりにくく、その分コストとリスクが発生します。 また、バグについても回答させていただいた通りです。 このあたりは変数名に正しい名前を付けるなどの目的と同義です。 ですので、データ構造については、知見が無い人が見てもなるべくわかりやすく、単純にしておくと良いかと存じます。 データ構造の例ですが、申し訳ありません。 よく考えないと私の方でもいい案が浮かびませんので、今回のデータ構造については、 今後、質問者様がプログラミングをしていく中で、ご参考いただければ幸いです。 尚、配列の他に、jsonやObject等があります。 こちらもご参考ください。
mi_

2017/01/16 08:53

分からないことが分からない状態ですので、何を勉強していくべきか、いろいろと参考になりました。 ありがとうございました!
mi_

2017/01/16 09:09

どの回答も大変ありがたいものでしたが、そのものズバリの部分をご提示いただきましたので、ベストアンサーに選ばせていただきました。
guest

0

#DB定義

書き込みの時間などは省いていますが、以下のようなテーブル構造になるかと思います。

sql

1 2-- 設問テーブル 3 4CREATE TABLE `question` ( 5 `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', 6 `sentence` varchar(256) NOT NULL DEFAULT '' COMMENT '質問文', 7 `orderNumber` int(11) DEFAULT NULL COMMENT '表示順', 8 PRIMARY KEY (`id`) 9) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='設問'; 10 11-- 選択肢テーブル 12 13CREATE TABLE `choice` ( 14 `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', 15 `parentId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '親ID', 16 `questionId` int(10) unsigned DEFAULT NULL COMMENT '設問ID', 17 `sentence` varchar(1000) DEFAULT NULL COMMENT '選択肢文言', 18 `orderNumber` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '表示順', 19 PRIMARY KEY (`id`) 20) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8mb4 COMMENT='選択肢'; 21 22-- 回答テーブル 23 24CREATE TABLE `answer` ( 25 `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', 26 `userId` int(10) unsigned NOT NULL COMMENT 'ユーザーID', 27 `questionId` int(10) unsigned NOT NULL COMMENT '設問ID', 28 `choiceId` int(10) unsigned NOT NULL COMMENT '選択肢ID', 29 PRIMARY KEY (`id`) 30) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='回答';

#サンプルデータ

sql

1INSERT INTO `question` (`id`, `sentence`, `orderNumber`) 2VALUES 3 (1,'職場までの通勤時間は?',2), 4 (2,'この案件を何で知りましたか?',1); 5 6INSERT INTO `choice` (`id`, `parentId`, `questionId`, `sentence`, `orderNumber`) 7VALUES 8 (1,0,1,'車で5分以内',1), 9 (2,0,1,'車で10分以内',2), 10 (3,0,1,'車で20分以内',3), 11 (4,0,1,'車で30分以内',4), 12 (5,0,1,'それ以上',5), 13 (6,0,2,'紹介',1), 14 (7,0,2,'看板',2), 15 (8,0,2,'チラシ',3), 16 (9,0,2,'フリーペーパー',4), 17 (10,9,2,'雑誌A',5), 18 (11,9,2,'雑誌B',6), 19 (12,9,2,'雑誌C',7), 20 (13,9,2,'雑誌D',8), 21 (14,0,2,'ネット',9), 22 (15,14,2,'ホームページ',10), 23 (16,14,2,'EPARK',11), 24 (17,14,2,'エキテン',12), 25 (18,14,2,'LINE',13), 26 (19,14,2,'Facebook',14), 27 (20,14,2,'Instagram',15), 28 (21,14,2,'その他',16);

この質問内容について、問題が複雑になっているのは、選択肢がツリー構造になっている点です。
ツリー構造がなければ、難易度はかなり低くなるのですが、ツリー構造が必須となると、MVCの知識がないと理解は難しいかと思われます。
まずは、ここまで理解できますでしょうか?

投稿2017/01/16 07:48

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

mi_

2017/01/16 08:51

具体的にテーブルの例までありがとうございます。 親IDという組み合わせ方をはじめて知りました。 ツリー構造は、イメージだけで、具体的なMVCの知識もない状態です。 ご提示いただいた内容は自分ではすぐに作れませんが、読んで理解はできました。 PHPは初心者で、構造の考え方は、見よう見まねの初心者のaccessで業務プログラムを作っていたときの発想のままでやっています。
退会済みユーザー

退会済みユーザー

2017/01/16 08:58 編集

MVCの知識がなくてもできないわけではないのですが、ソースコードは比較にならないくらい複雑になります。簡潔に書く場合は、SQLの問い合わせが多すぎてしまう…よいう方が正確ですね。PHPのソースコードまで提示するとなると、おそらくサンプルレベルでも、1日2日程度の時間がかかると思われますので、一旦はテーブル定義で留めました。
mi_

2017/01/16 09:07

ソースコードが複雑になるか、SQLの問い合わせが多くなるか、なのですね。まわりにプログラムをできる人がいないので、いろいろな考え方が大変勉強になります。 テーブル定義をいただいたことで、大変ヒントになりました。 ありがとうございました。
退会済みユーザー

退会済みユーザー

2017/01/16 09:18

この課題ちょっと面白そうなので、のちのち、Quitaにでもコードを上げておこうと思います。気長に待ってみてください。
mi_

2017/01/16 09:34

ありがとうございます!
退会済みユーザー

退会済みユーザー

2017/01/16 10:00

Quitaに記述する場合、前提条件として、質問文をそのまま掲載することが想定されますが、問題はございませんか?
mi_

2017/01/16 10:02

まったく問題ありません。 Quitaは先ほどユーザー登録したくらいの状態でして、掲載されたときには教えていただけると大変ありがたいです。
退会済みユーザー

退会済みユーザー

2017/01/16 10:04

Quitaで私のアカウントをフォローしておけば、フィードに表示されます。
mi_

2017/01/16 10:07

できました。 ありがとうございました!
guest

0

arrayになっている部分が配列になります。

$survey= array(
"sur1"=> "val"

上記の場合、以下のようにすると、文字列"val"が取得できます。
$survey["sur1"]

"sur1"の部分に何が入るのかも不明な場合

foreach ($survey as $key => $val) {
}
とすることで、$keyに"sur1"、$valに"val"を取得できます。

php

1$survey= array( 2 "sur1"=> "val1", 3 "sur2"=> "val2", 4 "sur3"=> "val3", 5 );

上記のような場合、sur1,val1, sur2,val2, sur3,val3
がそれぞれ取得できます。

もし、文字列"val1"ではなく、arrayかもしれない場合、

php

1foreach ($survey as $key => $val){ 2 if (is_array($val)) { 3 foreach ($val as $subval) { 4 } 5 } else { 6 // string 7 } 8}

という感じで参照する。

subvalが配列かハッシュかを判断するのであれば、

php

1function is_assoc($_array) { 2 if ( !is_array($_array) || empty($array) ) { 3 return -1; 4 } 5 foreach (array_keys($_array) as $k => $v) { 6 if ($k !== $v) { 7 return true; 8 } 9 } 10 return false; 11}

http://php.net/manual/ja/function.is-array.php

投稿2017/01/16 07:52

t_obara

総合スコア5488

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

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

mi_

2017/01/16 08:46

具体的にありがとうございます! 今後も見直させていただき、活用させていただきたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問