PHPでControllerからViewへ配列を渡す方法

PHP でControllerからViewへ、またViewからControllerへ配列を渡すことがありますよね。

でも普通の方法だとViewでエラーになってしまったり、改行コードとして崩れてしまうと思います。

それを解決する方法をお伝えします。

目次

$_SESSION

$_SESSIONを使えば簡単に配列を渡すことが出来ます。

これが一番簡単な方法と言えるかもしれません。

が、向いているケースとしては

・ページ遷移またぎ

・ログイン情報

・一時保存

と言えるので、POSTの代わりにはしない方が良いです。

PHP
$_SESSION['test'] = array('test1', 'test2');
PHP(送信先)
var_dump($_SESSION['test']);

name[]+foreach+$_POST

一番実務で使う方式がこれです。

Viewでname属性にそのまま配列を入れるとArrayとなってしまったり、<br/>と改行コードに変換されてしまったりしてしまいます。

それを防ぐためにname属性をname[]とし、foreachで値を1つずつ入れていきます。

こうすることで同じ配列を入れることができます。

また、$_POSTで取得すれば元の形の配列として取得することが出来ます。

また、htmlspecialcharsはXSS対策として必須です!

PHP
$test = array('test1', 'test2');
HTML
<form method="post" action="next">
<?php foreach ($test as $value): ?>
    <input type="hidden" name="test[]" value="<?= htmlspecialchars($value, ENT_QUOTES) ?>">
<?php endforeach; ?>
</form>
PHP(送信先)
$test = $_POST['test'] ?? []; //undefined対策
var_dump($test);

JSON

複雑なデータ構造のときに使う、JSONを使う手もあります。

向いているケースとしては

・多次元配列

・JavaScriptとの連携

・API的な処理

ですので、一般的にはname[]+foreach+$_POSTをおすすめします。

PHP
$test = array('test1', 'test2');
HTML
<input type="hidden" name="test" value='<?= json_encode($test) ?>'>
PHP(送信先)
$test = json_decode($_POST['test'] ?? '', true) ?? [];
var_dump($test);

筆者の感想

正解が2つある問題の処理をどうするか考えていました。

PHP(Controller-問題)
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で配列を作ることにしました。

HTML(View)
<?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']) ?>">
PHP(Controller-回答処理)
// 解答の配列
$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に配列を持てると知りました。

HTML(View)
<?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

配列を指定の文字列で区切って出力します。

PHP
// 回答処理
public function answer(){

  ...

  // セッションに情報を保持
  $_SESSION['quiz']['results'][] = [
      ...
      'correct' => $correct,
      ...
  ];
}

// 結果表示
public function result()
{
    $results = $_SESSION['quiz']['results'];
}
HTML(View)
  <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を使う手もある

この記事が参考になったら嬉しいです。

  • URLをコピーしました!
目次