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

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

ただいまの
回答率

87.61%

【PHP/Ajax/MySQL】ajaxからPHP呼び出し時にエラーが発生する。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,784

score 16

前提・実現したいこと

・PHP、Javascript(ajax,datatables)、MYSQLを使って検索サイトを構築しています。
・HTML画面に表示するテーブル構成として、theadは固定にし、
tbodyをajaxを使って条件などを変えたSQLを発行し、データ抽出し、表示させる想定です。
・今はjs(ajax_table.js)のphp呼び出し時にエラーが発生しているように見受けられます。
・datatablesのajaxに関する使い方に問題があると考えていますが、
原因と解決方法をご教授頂けますようお願いいたします。

発生している問題・エラーメッセージ

chromeのConsoleより、以下メッセージが表示されます。
Uncaught TypeError: Cannot read property 'length' of undefined

該当のソースコード

<!doctype html>
<html lang="ja">
  <head>
 省略
  </head>
<body>
     <table id="sample" class="table  table-bordered table-hover table-responsive table-sm">

       <thead>
       <tr class="table-primary">
       <th>苗字</th>
       <th>名前</th>
       <th>学年</th>
       </tr>
      </thead>

</table>

 省略

<script src="ajax_table.js"></script>
//ajax_table.js

$(document).ready(function() {
  $.extend( $.fn.dataTable.defaults, {
     language: {
         url: "http://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Japanese.json"
     }
 });
      $('#sample').dataTable ({
        lengthMenu: [ 100, 200, 300, 400, 500 ],
         "ajax" : {
         'url' : 'ajax_show_all.php',
        'datatype' : 'json', //受け取りデータの種類
        "columns": [
            { "data": "lastname" },
            { "data": "firstname" },
            { "data": "grade" }
          ]
           }
          });
//ajax_show_all.php
<?php

// データベース接続クラスPDOのインスタンス$dbhを作成する
try {
    $dbh = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8mb4", $dbuser, $dbpass);
// PDOExceptionクラスのインスタンス$eからエラーメッセージを取得
} catch (PDOException $e) {
    // 接続できなかったらvar_dumpの後に処理を終了する
    var_dump($e->getMessage());
    exit;
}

// データ取得用SQL
// 値はバインドさせる
$sql = 'SELECT lastname,firstname,grade FROM tbl where grade in (1,2,3,4)';

// SQLをセット
$stmt = $dbh->prepare($sql);
// SQLを実行
$stmt->execute();

// あらかじめ配列$productListを作成する
// 受け取ったデータを配列に代入する
// 最終的にhtmlへ渡される
$productList = array();

// fetchメソッドでSQLの結果を取得
// 定数をPDO::FETCH_ASSOC:に指定すると連想配列で結果を取得できる
// 取得したデータを$productListへ代入する
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
    $productList[] = array(
      'lastname' => $row['lastname'],
      'firstname' => $row['firstname'],
      'grade' => $row['grade']

    );
}

// ヘッダーを指定することによりjsonの動作を安定させる
 header('Content-type: application/json');
// htmlへ渡す配列$productListをjsonに変換する
 echo json_encode($productList,JSON_UNESCAPED_UNICODE);

試したこと

原因切り分けとして、jsファイルの「'ajax_show_all.php'」部分を
phpファイルから返却される予定の仮データ(jsonファイル)に置き換えると、上手く表示されました。

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

Ajaxから実行しているPHPのほうでエラーが出ていたりしていませんか?デバッグ・エラーログ確認してみてください。
PHPからの出力にJSONデータ以外が入り込んでいてJSONが正しく生成されず、lengthが正しくとれずに提示のエラーとなっているように思います。

あとはその「予定の仮データ」とは階層が違うとか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/03 09:53 編集

    ご回答ありがとうございます。
    ご指摘の通り、仮データとPHPからの返却データのデータ形式が違うためにエラーとなっていることがわかりました。
    具体的には以下の通りです。"data"部分です。

    ①仮データ(jsonファイル)
    {
    "data":[
    {"lastname": "テストA", "firstname": "テストA", "grade": "4"},
    {"lastname": "テストB", "firstname": "テストB", "grade": "4"}
    ]
    }

    ②ajax_show_all.phpから返却されるデータ

    [
    {"lastname":"テストA","firstname":"テストA","grade":"4"},
    {"lastname":"テストB","firstname":"テストB","grade":"4"}
    ]

    対処として、②に何らかの方法で"data"構造を付与するか、
    ajaxが②(columns定義部分?)で受け取れるようにするかだと考えているのですが、
    具体的な実装方法がわかりませんでした。
    おわかるになるようでしたら、教えて頂けないでしょうか。

    参考として、①はdatatablesサイトのexamplesをベースにした結果です。
    https://datatables.net/examples/ajax/objects.html

    キャンセル

  • 2019/05/03 10:49

    でしたら連想配列1個追加するだけですね。

    echo json_encode($productList,JSON_UNESCAPED_UNICODE);

    echo json_encode(['data'=>$productList],JSON_UNESCAPED_UNICODE);

    か、
    $productList = array();

    $productList = [];
    $productList['data'] = [];

    ※[] はarray()の短縮構文でPHP5.4以降でしたらこちらが主流です
    https://qiita.com/tadsan/items/157969b338fd8b782b21
    #配列はarrayで作る

    キャンセル

  • 2019/05/03 12:04 編集

    コメント頂いたやり方で無事にajaxでデータを受け取れ、画面表示までできました。
    大変助かりました。ありがとうございました。

    キャンセル

  • 2019/05/03 13:17

    解決されたようで何よりです。
    配列も多次元になると形が見えにくくなるものですが、箱に入れていくイメージで丁寧に考察していくと案外単純なことの繰り返しなので、あとは慣れだけと思います

    キャンセル

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

  • ただいまの回答率 87.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る