PHP でControllerからViewへ、またViewからControllerへ配列を渡すことがありますよね。
でも普通の方法だとViewでエラーになってしまったり、改行コードとして崩れてしまうと思います。
それを解決する方法をお伝えします。
$_SESSION
$_SESSIONを使えば簡単に配列を渡すことが出来ます。
これが一番簡単な方法と言えるかもしれません。
が、向いているケースとしては
・ページ遷移またぎ
・ログイン情報
・一時保存
と言えるので、POSTの代わりにはしない方が良いです。
$_SESSION['test'] = array('test1', 'test2');var_dump($_SESSION['test']);name[]+foreach+$_POST
一番実務で使う方式がこれです。
Viewでname属性にそのまま配列を入れるとArrayとなってしまったり、<br/>と改行コードに変換されてしまったりしてしまいます。
それを防ぐためにname属性をname[]とし、foreachで値を1つずつ入れていきます。
こうすることで同じ配列を入れることができます。
また、$_POSTで取得すれば元の形の配列として取得することが出来ます。
また、htmlspecialcharsはXSS対策として必須です!
$test = array('test1', 'test2');<form method="post" action="next">
<?php foreach ($test as $value): ?>
<input type="hidden" name="test[]" value="<?= htmlspecialchars($value, ENT_QUOTES) ?>">
<?php endforeach; ?>
</form>$test = $_POST['test'] ?? []; //undefined対策
var_dump($test);JSON
複雑なデータ構造のときに使う、JSONを使う手もあります。
向いているケースとしては
・多次元配列
・JavaScriptとの連携
・API的な処理
ですので、一般的にはname[]+foreach+$_POSTをおすすめします。
$test = array('test1', 'test2');<input type="hidden" name="test" value='<?= json_encode($test) ?>'>$test = json_decode($_POST['test'] ?? '', true) ?? [];
var_dump($test);筆者の感想
正解が2つある問題の処理をどうするか考えていました。
public function question()
{
...
$reading_count = 0;
$before_id = 0;
$correct_array = [];
foreach ($tmp_question as $k1 => $v1){
foreach ($reading as $k2 => $v2){
if($v1['id'] === $v2['question_id']){
// 正解(複数ある場合を考慮)
if ($before_id === $v2['question_id']){
$reading_count++;
$question[$k1]['reading'][$reading_count] = $v2['reading'];
}else{
$question[$k1]['reading'][0] = $v2['reading'];
$reading_count = 0;
}
$before_id = $v2['question_id'];
}
}
}
// セッションに保存
$_SESSION['quiz']['question'] = $question;
...
// セッションの値を変数に保存
$current = $_SESSION['quiz']['current'];
$question = $_SESSION['quiz']['question'];array_pushを使った方が良かったと思うけれど、わかりやすくcount用変数を使って書きました。
それをセッションに持たせ、Viewで使える変数に保存してViewを表示するという流れです。
そして、ViewからControllerに値を取得する時は$_POSTで取得するのがベストかなと思います。
ただ、上記でいうと$question[(n)][reading]はまだ配列の状態なんですよね。
なので、配列の個数分 type=”hidden” フィールドを作ってPOSTで送った先のControllerで配列を作ることにしました。
<?php foreach($question['reading'] as $k => $v):?>
<input type="hidden" name="correct_<?=$k?>" value="<?=$v?>">
<?php endforeach; ?>
<input type="hidden" name="correct_count" value="<?= count($question['reading']) ?>">// 解答の配列
$correctReadings = [];
$correct_count = (int)$_POST['correct_count'];
for($i=0;$i<$correct_count;$i++){
$tmp_correct = $_POST['correct_'.$i];
array_push($correctReadings,$tmp_correct);
}
$answer = trim($_POST['answer']);
// セッションに情報を保持
$_SESSION['quiz']['results'][] = [
'answer' => $answer,
'correct' => $correctReadings,
'is_correct' => in_array($answer, $correctReadings, true)
];とりあえずこうすることで成功しました。
成功したのはいいものの、なんかコードが長すぎるよなぁ・・・
そこで、name[]+foreach+$_POSTの方法でvalueに配列を持てると知りました。
<?php foreach($question['reading'] as $k => $v):?>
<input type="hidden" name="correct[]" value="<?= $v ?>">
<?php endforeach; ?>つまり、上の例だと「correct」→「correct[]」にするだけで、valueに配列が入りました。
え、何それだけ?
確かに、POSTされてきた値をvar_dumpすると、先ほど作った配列と同じだ・・・
例):薔薇(音読み)
array(2) { [0]=> string(12) “しょうび” [1]=> string(9) “そうび” }
うーん、無知は罪ですね(泣)
おまけ:implode
配列を指定の文字列で区切って出力します。
// 回答処理
public function answer(){
...
// セッションに情報を保持
$_SESSION['quiz']['results'][] = [
...
'correct' => $correct,
...
];
}
// 結果表示
public function result()
{
$results = $_SESSION['quiz']['results'];
} <table class="w-full border-collapse border border-gray-400">
<thead>
<tr>
<th class="border border-gray-300">正解</th>
</tr>
</thead>
<tbody>
<?php foreach ($results as $k => $r): ?>
<tr>
<td class="border border-gray-300 text-center"><?= htmlspecialchars(implode('/',$r['correct'])) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
配列としてそのまま出力するより、断然それっぽくなりました。
まとめ
- $_SESSIONを使えば一番簡単に配列渡せる
- name[]+foreach+$_POSTで王道の配列渡しができる。
- 小規模であればJSONを使う手もある
この記事が参考になったら嬉しいです。

