Ajaxで連動したselectタグを生成する方法 (PHP)


やりたいこと

  • 親selectタグで選択された項目にカテゴライズされた子selectタグをAjaxで生成する

例)自動車メーカー(TOYOTA,NISSAN,HONDA)に連動した各メーカーの車種のselectタグを生成

*セキュリティ対策は実装出来ておりません。

  • 自動車メーカー maker テーブル(親)
id maker_name
1 TOYOTA
2 NISSAN
3 HONDA
  • 車種テーブル model テーブル(子)
id maker_id model_name
1 1 アクア
2 1 アルフォード
3 1 カローラ
4 1 プリウス
5 1 クラウン
6 2 ジューク
7 2 ノート
8 2 キューブ
9 2 セレナ
10 3 オデッセイ
11 3 フィット
12 3 N-BOX
13 3 ステップワゴン
14 3 CR-V
15 3 CR-Z
index.php
<?php
  //DBへ接続
  try {
    $dsn = 'mysql:host=localhost;dbname=car_maker;charset=utf8';
    $user = 'username'; //root
    $pass = 'password'; //root
    $pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_EMULATE_PREPARES => false));
  } catch (Exception $e) {
    exit('データベース接続失敗'.$e->getMessage());
  }
  //makerテーブル から値を取得し、 id と name を $maker_list配列 に格納
  $sql = "SELECT * FROM maker";
  $stmt = $pdo->query($sql);
  $maker_list = array();
  while($row = $stmt -> fetch(PDO::FETCH_ASSOC)){
    $maker_list[$row['id']] = $row['maker_name'];
  }
?>

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script src="js/jquery-1.12.4.min.js" charset="utf-8"></script>
    <script type="text/javascript">
      $(function(){
        //selectタグ(親) が変更された場合
        $('[name=car_maker]').on('change', function(){
          var maker_val = $(this).val();

          //maker_val値 を select.php へ渡す
          $.ajax({
            url: "select.php",
            type: "POST",
            dataType: 'json',
            data: {
              maker_id: maker_val
            }
          })
          .done(function(data){
            //selectタグ(子) の option値 を一旦削除
            $('.car_model option').remove();
            //select.php から戻って来た data の値をそれそれ optionタグ として生成し、
            // .car_model に optionタグ を追加する
            $.each(data, function(id, name){
              $('.car_model').append($('<option>').text(name).attr('value', id));
            });
          })
          .fail(function(){
            console.log("失敗");
          });

        });
      });
    </script>
    <title>Ajax Sample</title>
  </head>
  <body>
    <h1>Ajax Sample</h1>
      <div class="">
        <span>自動車メーカー:</span>
        <select class="car_maker" name="car_maker">
          <option>選択して下さい</option>
          <?php foreach($maker_list as $key => $maker_name){
            echo '<option name="" value="'.$key.'">'.$maker_name.'</option>';
          }?>
        </select>
        <span>車種:</span>
        <select class="car_model" name="car_model">
          <option class="">選択して下さい</option>
        </select>
      </div>
  </body>
</html>
select.php
<?php
  //直接のページ遷移を阻止
  $request = isset($_SERVER['HTTP_X_REQUESTED_WITH']) ? strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) : '';
  if($request !== 'xmlhttprequest') exit;
  //DBへの接続
  //本来は db_connect関数 を作成して、DRYにした方が良いです。
  try {
    $dsn = 'mysql:host=localhost;dbname=car_model;charset=utf8';
    $user = 'username';
    $pass = 'password';
    $pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_EMULATE_PREPARES => false));
  }
  catch (Exception $e) {
    exit('データベース接続失敗'.$e->getMessage());
  }
  //Ajaxで渡ってきた値をもとに modelテーブル から該当する model を抽出
  $maker_no = $_POST['maker_no'];
  $sql = 'SELECT * FROM model WHERE maker_id = :maker_id';
  $stmt=$pdo->prepare($sql);
  $stmt->bindValue(':maker_id', (int)$maker_no, PDO::PARAM_INT);
  $stmt->execute();

  //抽出された値を $model_list配列 に格納
  $model_list = array();
  while($row = $stmt -> fetch(PDO::FETCH_ASSOC)){
    $model_list[$row['id']] = $row['maker_name'];
  }
  header('Content-Type: application/json');
  //json形式で index.php へバックする
  echo json_encode($model_list);
 ?>