🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
foreach

foreachは、List・Collection・Arrayといったデータ構造の各要素に対して繰り返し処理を実行するために扱われる、制御構造の構文です。

多次元配列

1次元配列内にさらに配列を格納している配列を、多次元配列と呼びます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

3回答

1357閲覧

[PHP]フォームで送信した配列をまとめて連想多次元配列にし、SQL処理したい。

nessie603

総合スコア4

foreach

foreachは、List・Collection・Arrayといったデータ構造の各要素に対して繰り返し処理を実行するために扱われる、制御構造の構文です。

多次元配列

1次元配列内にさらに配列を格納している配列を、多次元配列と呼びます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2019/10/17 03:31

編集2019/10/17 03:38

前提・実現したいこと

PHP初心者です。
現在、ブラウザ上で各セルにフォーム機能を持たせたテーブルを作り、
各フォームに値を入力し、一括でUPDATE出来るWebアプリケーションを作ろうとしています。
実際には、以下の様なコードでやりたいことは実現できているのですが、
SQL処理を二回foreachしているので、負荷がかかってあまり推奨できるやり方ではありません。。。

該当のソースコード

PHP

1//POSTする側のコードです。 2<!DOCTYPE html> 3<html lang="en"> 4<head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>データを更新する</title> 9</head> 10<body> 11 <pre> 12 <?php 13 $tab_name = $_POST["table_title"]; 14 $stmt = $db->query("SELECT*FROM $tab_name"); 15 echo "<p>更新したい対象データを入力し、新しいデータに書き換えてください</p>"; 16 echo "<h1>$tab_name</h1>"; 17 18 $col = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='mydb'AND TABLE_NAME='".$tab_name."'"; 19 $stmt2 =$db->query($col); 20 if(!$col){//もし、$colの内容が変だったら、エラーメッセージを出すようにする 21 echo $db->errorInfo(); 22 exit(); 23 } 24 echo '<form action="updateDetail.php" method="POST">'; 25 echo "<table border=1 style=border-collapse:collapse>"; 26 //繰り返し処理を使って、テーブルの見出しを表示 27 //配列からテーブルの見出しの情報のみを取り出し 28 echo "<tr>"; 29 while ($retu=$stmt2->fetch(PDO::FETCH_ASSOC)){ 30 foreach($retu as $koumoku){ 31 32 echo "<th>"; 33 echo"$koumoku"; 34 echo "</th>"; 35 } 36 } 37 echo "</tr>"; 38 //テーブルを繰り返しを使って描画する 39 40 echo "<tr><th></th>"; 41 echo "<th>fullname"; 42 echo "</th>"; 43 echo "<th>age"; 44 echo "</th>"; 45 echo "</tr>"; 46 foreach($stmt as $row){ 47 echo "<tr>"; 48 echo "<td>"; 49 echo '<input type="hidden" name="id[]" value='."$row[id]".'>'; 50 echo '<input type="hidden" name="tab_name" value='."$tab_name".'>'; 51 echo "</td>"; 52 53 echo "<td>"; 54 echo '<input type="text" name="fullname[]" value='."$row[fullname]".'>'; 55 echo "</td>"; 56 57 echo "<td>"; 58 echo '<input type="text" name="age[]" value='."$row[age]".'>'; 59 echo "</td>"; 60 61 echo "</tr>"; 62 63 } 64 65 ?> 66 </table> 67 <input type="submit" value="送信する"> 68 </form> 69 70 </pre> 71 72 <br><a href="updateTableSelect.php">戻る</a> 73</body> 74</html> 75 76//↓以下フォーム送信後の内容です 77 78<!DOCTYPE html> 79<html lang="en"> 80<head> 81 <meta charset="UTF-8"> 82 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 83 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 84 <title>Document</title> 85</head> 86<body> 87 <p>データを更新しました</p> 88 <?php 89 $fullname = $_POST['fullname']; 90 $age = $_POST["age"]; 91 $id= $_POST["id"]; 92 $table = $_POST["tab_name"]; 93 94 echo '<pre>'; 95 96 echo '<a href="toppage.php">戻る</a>'; 97 98 //以下の方法はSQLに負荷がかかるので推奨されない 99 //fullnameをidと紐づけて更新する 100 $Fullname=array_combine($id,$fullname); 101 foreach($Fullname as $keyid=>$valuename){ 102 $sql="UPDATE $table SET fullname=:fullname WHERE id=:id"; 103 $stm=$db->prepare($sql); 104 $stm->bindValue(':fullname',"$valuename"); 105 $stm->bindValue(':id',"$keyid"); 106 $stm->execute(); 107 } 108 109 //ageをidと紐づけて更新する 110 $Age=array_combine($id,$age); 111 foreach($Age as $keyid=>$valueage){ 112 $sql2="UPDATE $table SET age=:age WHERE id=:id"; 113 $stm=$db->prepare($sql2); 114 $stm->bindValue(':age',"$valueage"); 115 $stm->bindValue(':id',"$keyid"); 116 $stm->execute(); 117 } 118 119 ?> 120

###試したこと
例えば、以下の様な配列を作成することができれば、

PHP

1array (size=2) 2 1 => 3 array (size=2) 4 'fullname' => string 'name1' (length=5) 5 'age' => string '10' (length=2) 6 2 => 7 array (size=2) 8 'fullname' => string 'name2' (length=5) 9 'age' => string '20' (length=2)

foreach をid単位で回して、fullnameとageをいっぺんに更新することが可能だと思うのですが…
連想多次元配列を上手く組めなくて苦戦しております。。。

###一例

PHP

1for($i=0;$i<10;$i++){ 2 $array=array( 3 "id"=>"$id[$i]", 4 array( 5 "name"=>"$fullname[$i]", 6 "age"=>"$age[$i]" 7 ) 8 );

上記の様な方法を考えたりもしましたが、配列の個数を指定しなければならない(制限を設けたくない)のと、
どの様にUPDATE繰り返し処理に持ち込めば良いのか、混乱してしまいよくわからなくなってしまいました。
スマートなやり方をご存知の方いらっしゃいましたら、是非お力添えをよろしくお願いいたします。
全体的に拙い説明で申し訳ありません。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答3

0

同じテーブルへのupdateなら、一度に出来ます。
$sql="UPDATE $table SET fullname = :fullname, age = :age WHERE id=:id";
みたいになるけど、$tableが外部由来で詰められていてSQLインジェクションの脆弱性をはらむのがこわい。
1とか2とか3とかにして、1だったらテーブルA、2だったら、3だったら、みたいにするべき。

POST受信データの検証をせずに処理しているけど大丈夫?
いくらプレースホルダーを使っているとは言え、
未送信データがあったりすることは想定しなくていいのだろうかと。
身内でしか使わないのかもしれないけど、テーブル名まで外部から受信しているのがちょっと怖いね。

echo '<input type="hidden" name="tab_name" value='."$tab_name".'>';

ここだけパラメータが配列化されていないようだけど。

投稿2019/10/17 03:43

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

nessie603

2019/10/17 05:05

ご回答ありがとうございます。 問題の解決には至りませんでしたが、脆弱性の問題など検討が必要な点のご指摘、ありがとうございました。 精進いたします。
nessie603

2019/10/17 07:46

参考サイトのご紹介ありがとうございます。 重ねてお礼申し上げます。 引き出しがとても少ないので、非常に参考になります。
guest

0

自己解決

UPDATE文1行のみで行ける方法に行き着いたので、記録をしておきます。

PHP

1<?php 2 //フォームから受け取った値を変数に格納する 3 $id= $_POST["id"]; 4 $fullname = $_POST['fullname']; 5 $age = $_POST["age"]; 6 7 //countメソッドを用い、受け取った要素の数をカウントできるようにする 8 $count = count($id); 9 10   //先ほどのカウント数をfor文に盛り込み、回数分処理を行う 11 try{ 12 $sql="UPDATE テーブル名 SET fullname=:fullname, age=:age WHERE id=:id"; 13 $stm=$db->prepare($sql); 14 for($i=0;$i<$count;$i++){ 15 //連想配列をarray()を使って作成し、SQL文を実行してしまう 16     $array=array("id"=>"$id[$i]","fullname"=>"$fullname[$i]","age"=>"$age[$i]"); 17 $stm->bindParam(':id', $array['id'], PDO::PARAM_INT); 18 $stm->bindParam(':fullname', $array['fullname'], PDO::PARAM_STR); 19 $stm->bindParam(':age', $array['age'], PDO::PARAM_INT); 20 $stm->execute();} 21 22 } 23 catch(\PDOException $e){ 24 echo $e->getMessage(); 25 } 26      27 28 ?>

とりあえず、これでいけましたが、まだ不完全なところはあるかもしれません。
(┣¨初心者なもので....)
より効率よく処理を高速化させる方法がある気がしており、このやり方だと遅いのかもしれません。。。
ひとまず解決とさせていただきますが、他にも方法はあると思いますので、ご提案ある方いらっしゃいましたらよろしくお願いいたします。

投稿2019/10/17 12:37

編集2019/10/18 02:10
nessie603

総合スコア4

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

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

0

すでに指摘がありますが$tableを外から持ってくるのは良くないですね
ホワイトリストをつくってin_arrayなどで完全一致をする処理が必要になります。

またupdateは2つにわける必要はないし、もしかりに分けるなら
トランザクションで処理しないと片方だけ修正されてしまう恐れもあります

投稿2019/10/17 03:56

yambejp

総合スコア116661

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

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

nessie603

2019/10/17 05:09

ご回答ありがとうございます。 確かに配列をちゃんと作れたら、二回に分ける必要も無い筈なのですよね。 自身の引き出しの少なさ故だと思います。 脆弱性に対するコメントもありがとうございました。精進いたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問