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

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

ただいまの
回答率

88.34%

MySQL+PHPでデータの取得方法について

解決済

回答 2

投稿 編集

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

kaya_miyoshi

score 23

下記コードで(MySQL8.0、PHP7、Windows 10、sampledb にはデータを格納済み)、

<?php
header("Content-Type: text/html; charset=UTF-8");

//データベース接続
$server = "localhost";
$userName = "testuser";
$password = "testuser";
$dbName = "sampledb";

$mysqli = new mysqli($server, $userName, $password, $dbName);

$result = $mysqli->query("create table if not exists sample (id integer primary key, name text, age integer)");

/**************/
/* データ取得 */
/**************/

if (isset($_GET["func"]) && $_GET["func"] == "get_data") {
    $stmt = $mysqli->query("select * from sample");
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $json = json_encode($rows);
    echo $json;
    exit();

/*********************************/
/* データ更新(削除、変更、追加)*/
/*********************************/

} else if (isset($_POST["func"]) && $_POST["func"] == "upd_data") {
    // データ受取
    $delid = $_POST["delid"];
    $delid = json_decode($delid, true);
    $upddata = $_POST["upddata"];
    $upddata = json_decode($upddata, true);
    $insdata = $_POST["insdata"];
    $insdata = json_decode($insdata, true);

    // トランザクション開始
    $db->beginTransaction();
    // データ削除
    if ($delid) {
        for ($i=0; $i<count($delid); $i++) {
            $sql = "DELETE FROM sample WHERE id=?";
            $stmt = $db->prepare($sql);
            $stmt->execute(array($delid[$i]["id"]));
        }
    }
    // データ変更
    if ($upddata) {
        for ($i=0; $i<count($upddata); $i++) {
            $sql = "UPDATE sample SET name=?, age=? WHERE id=?";
            $stmt = $db->prepare($sql);
            $stmt->execute(array($upddata[$i]["name"], $upddata[$i]["age"], $upddata[$i]["id"]));
        }
    }
    // データ追加
    if ($insdata) {
        for ($i=0; $i<count($insdata); $i++) {
            $sql = "INSERT INTO sample (name, age) VALUES (?, ?)";
            $stmt = $db->prepare($sql);
            $stmt->execute(array($insdata[$i]["name"], $insdata[$i]["age"]));
        }
    }
    // トランザクション終了
    $db->commit();
    exit();
}
$db = null;
?>

<html>
<center>
<head>
<script type="text/javascript">

var Ajax = new XMLHttpRequest();

// 削除対象IDを格納する配列
var delid = [];

// 変更データを格納する配列
var upddata = [];

// 新規登録データを格納する配列
var insdata = [];

window.onload = getSample;

/************/
/* 一覧表示 */
/************/

function getSample() {
    var rows, row, i, out;
    var url = "sample.php" + "?dummy=" + new Date().getTime() + "&func=" + "get_data";
    Ajax.open("GET", url, true);
    Ajax.send(null);
    Ajax.onreadystatechange = function() {
        if (Ajax.readyState == 4 && Ajax.status == 200) {
            out = '<table border="1" id="sampletb">';
            out += '<tr>';
            out += '<th>削除</th>';
            out += '<th>ID</th>';
            out += '<th>氏名</th>';
            out += '<th>年齢</th>';
            out += '</tr>';
            var res = Ajax.responseText;
            if (res) {
                rows = JSON.parse(res);
                for (i in rows) {
                    out += '<tr>';
                    out += '<td><input type="checkbox" id="'+i+':0" onClick="delCheck(this);"></td>';
                    out += '<td><input type="text" id="'+i+':1" value='+rows[i]["id"]+' disabled></td>';
                    out += '<td><input type="text" id="'+i+':2" value="'+rows[i]["name"]+'" onChange="updCheck(this)";></td>';
                    out += '<td><input type="text" id="'+i+':3" value="'+rows[i]["age"]+'" onChange="updCheck(this)";></td>';
                    out += '</tr>';
                }   
            }
            out += '</table>';
            out += '<p>';
            out += '<button type="button" onClick="addRow();">'+"行追加"+'</button>';
            out += '<button type="button" onClick="Upd();">'+"更新"+'</button>';
            out += '</p>';
            document.getElementById("result").innerHTML = out;
        }
    }
}

/**********/
/* 行追加 */
/**********/

function addRow() {
    var el = document.getElementById('sampletb');
    var i = el.rows.length;
    var insertRow = el.insertRow(i);
    var insertCell0 = insertRow.insertCell(0);
    var insertCell1 = insertRow.insertCell(1);
    var insertCell2 = insertRow.insertCell(2);
    var insertCell3 = insertRow.insertCell(3);
    insertRow.style.backgroundColor = 'blue';
    // 1:insid, 2:name, 3:age
    insertCell0.innerHTML = '<td><input type="checkbox"></td>';
    insertCell1.innerHTML = '<input type="text" id="'+i+':1" value="'+i+'" style="width:20px;">';
    insertCell2.innerHTML = '<input type="text" id="'+i+':2" value="" onChange="insCheck(this)";>';
    insertCell3.innerHTML = '<input type="text" id="'+i+':3" value="" onChange="insCheck(this)";>';
}

/************/
/* 新規登録 */
/************/

function insCheck(e) {
    var index = e.id.indexOf(":");
    var row = e.id.substring(0, index);
    var insid = document.getElementById(row+':1').value;
    var name = document.getElementById(row+':2').value;
    var age = document.getElementById(row+':3').value;
    // 最初の登録処理
    if (insdata.length == 0) {
        insdata.push({"insid":insid, "name":name, "age":age});
        return;
    }
    // 2件目以降の登録処理
    // 重複がある場合の登録処理
    for (var i=0; i<insdata.length; i++) {
        if (insdata[i]["insid"] == insid) {
            // 配列から除外
            insdata.splice(i, 1);
            // 配列に追加
            insdata.push({"insid":insid, "name":name, "age":age});
            return;
        } 
    }
    // 重複がない場合の登録処理
    insdata.push({"insid":insid, "name":name, "age":age});
}

/********/
/* 変更 */
/********/

function updCheck(e) {
    e.parentNode.style.backgroundColor = 'yellow';
    var row = e.id.substr(0, e.id.indexOf(":"));
    var tid = document.getElementById(row+':1').value;
    var name = document.getElementById(row+':2').value;
    var age = document.getElementById(row+':3').value;
    // 最初の変更処理
    if (upddata.length == 0) {
        upddata.push({"id":tid, "name":name, "age":age});
        return;
    }
    // 2件目以降の変更処理
    // 重複がある場合の変更処理
    for (var i=0; i<upddata.length; i++) {
        if (upddata[i]["id"] == tid) {
            // 配列から除外
            upddata.splice(i, 1);
            // 配列に追加
            upddata.push({"id":tid, "name":name, "age":age});
            return;
        }
    }
    // 重複がない場合の変更処理
    upddata.push({"id":tid, "name":name, "age":age});
}

/********/
/* 削除 */
/********/

function delCheck(e) {
    var tid = document.getElementById(e.id.replace(':0',':1')).value;
    // チェック入れたとき
    if (e.checked == true) {
        e.parentNode.parentNode.style.backgroundColor = 'red';
        delid.push({"id":tid});
    // チェック外したとき
    } else if (e.checked == false) {
        e.parentNode.parentNode.style.backgroundColor = '';
        for (var i=0; i<delid.length; i++) {
            if (delid[i]["id"] == tid) {
                delid.splice(i, 1);
            }
        }
    }
}

/************/
/* 更新処理 */
/************/

function Upd() {
    delid2 = JSON.stringify(delid);
    upddata2 = JSON.stringify(upddata);
    insdata2 = JSON.stringify(insdata);
    url = "sample.php";
    Ajax.open("POST", url, true);
    Ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    Ajax.send("func=" + "upd_data" + "&delid=" + delid2 + "&upddata=" + upddata2 + "&insdata=" + insdata2);
    Ajax.onreadystatechange = function() {
        if (Ajax.readyState == 4 && Ajax.status == 200) {
            getSample();
            // 配列初期化
            delid.length=0;
            upddata.length=0;
            insdata.length=0;
        }
    }
}

</script>
</head>
<body>
<div id="result"></div>
</body>
</center>
</html>

ー 問題点 ー

・(isset($_GET["func"]))、($_GET["func"] == "get_data") の両方とも FALSE を返す。

・fetchAll() を使うと Call to undefined method mysqli_result::fetchAll() のエラーになる。

データ取得をうまくするにはどうすればよいでしょうか?

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • m.ts10806

    2018/11/13 14:10

    複数アカウントですか?名前からどういう事情があるかわかりませんが、よくないですね。この質問をどう取り扱うんでしょうか。

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2018/11/13 14:30

    ログインし直したときに間違ってSNSアカウントで登録ボタンを押してしまったためです。この質問はこのまま続け、解決すれば新しいアカウントのみで質問するようになると思います。不正などの意図は全くないです。

    キャンセル

  • kaya_miyoshi

    2018/11/13 16:40 編集

    2つのファイル(phpファイルとhtmlファイル)に分けました。ログインし直したときに間違ってSNSアカウントで登録ボタンを押してしまいました。この質問は前のアカウントが使えるようになったため続けられます。

    キャンセル

回答 2

checkベストアンサー

+1

要件確認部分もあるのですが、ひとまずわかるほうだけ。

・fetchAll() を使うと Call to undefined method mysqli_result::fetchAll() のエラーになる。 

「そんなメソッドないよ」ということです。
そういうときはPHPマニュアルを確認してください。
PHPマニュアル:mysqli_result

/* メソッド */
bool data_seek ( int $offset )
mixed fetch_all ([ int $resulttype = MYSQLI_NUM ] )
mixed fetch_array ([ int $resulttype = MYSQLI_BOTH ] )
array fetch_assoc ( void )
object fetch_field_direct ( int $fieldnr )
object fetch_field ( void )
array fetch_fields ( void )
object fetch_object ([ string $class_name = "stdClass" [, array $params ]] )
mixed fetch_row ( void )
bool field_seek ( int $fieldnr )
void free ( void )

あるのは「fetch_all」ですね。mysqliオブジェクトなので引数のTYPEもPDOではありません。

ただ、PDOの機能を使いたいような記述をされていますが冒頭でmysqliオブジェクトを利用しています。
どちらかに統一されたほうが良いでしょう。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/14 13:22

    デバッグは確かにツール整えるのも良いですが、よほどグループで開発を進めていくようなことでない限りvar_dumpしたりログファイルに吐き出して確認したりで充分です。それも立派なデバッグです。

    揚げ足とりではないのですが、
    急にfetch_allにかえてますよね。
    2018/11/13 16:41時点ではfetchAll でデータが取れていると仰っています。
    情報が正確でないとアドバイスも意味がなくなります。
    データがとれているということは質問にあるエラーも解消されたと言うことになり、この質問はクローズに向かうと思うのですが、そのあたりは如何でしょうか?

    現在起きている問題と質問時点でのか問題が違うのであれば要件の変化となり、「質問内容への回答」にはなりません。
    現状を整理して一度クローズして新しく質問を建て直すか、質問文に最新の情報を追記してください。

    キャンセル

  • 2018/11/14 13:32

    以前fetchAllでデータは取れていました。さっきやるとエラーが出ました。fetch_allに変えるとデータが取れていますのでfetch_allで行きます。この質問はいったん解決とします。ありがとうございました。

    キャンセル

  • 2018/11/14 13:37

    >以前fetchAllでデータは取れていました。さっきやるとエラーが出ました。fetch_allに変えるとデータが取れていますのでfetch_allで行きます。

    メソッド名が変更になる仕様変更は滅多にあるものではないので、もともとpdoで書かれていたのではないでしょうか。
    回答にも書いたように「これだといける」のような手探りで進めるのではなくphpマニュアルを確認して確実に仕様通りの機能を仕様通りに使ってください。
    プログラムは指示した通りにしか動きません。

    キャンセル

+1

長いので、コードは見ていません。
問題点から、問題箇所っぽいものを想定しています。

(isset($_GET["func"]))、($_GET["func"] == "get_data") の両方とも FALSE を返す。

GET のパラメータがうまく渡っていません。意図したデータが有るかvar_dumpでもしてみてください。変数遷移が追えるよう、デバッグ環境を整えることをオススメします。

・fetchAll() を使うと Call to undefined method mysqli_result::fetchAll() のエラーになる。 

mysqli と PDO をごっちゃにして使用してます。
どちらか一方に寄せてください。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/13 14:13

    $rows = $stmt->fetchAll($resulttype = MYSQLI_NUM);

    ...としました。

    デバッグ環境ですが、Netbeansで環境を作っているのですが、php.iniに

    zend_extension="C:/php/php_xdebug-2.7.0beta1-7.2-vc15-x86_64.dll"
    xdebug.remote_enable=1
    xdebug.remote_handler=dbgp
    xdebug.remote_host=127.0.0.1
    xdebug.remote_port=9000

    としても、XDebugでブレークポイントを設置してステップ実行できません。

    どうすればいでしょうか?

    $_GETはXDebugでfilter_inputを使うように言われています。

    if (filter_input(INPUT_GET, 'func') && filter_input(INPUT_GET, 'get_data')) {

    ...にしています。

    デバッグ環境の作り方を知りたいです。

    キャンセル

  • 2018/11/13 16:42

    $rows = $stmt->fetchAll($resulttype = MYSQLI_NUM);

    ...としました。

    デバッグ環境ですが、Netbeansで環境を作っているのですが、php.iniに

    zend_extension="C:/php/php_xdebug-2.7.0beta1-7.2-vc15-x86_64.dll"
    xdebug.remote_enable=1
    xdebug.remote_handler=dbgp
    xdebug.remote_host=127.0.0.1
    xdebug.remote_port=9000

    としても、XDebugでブレークポイントを設置してステップ実行できません。

    どうすればいでしょうか?

    $_GETはXDebugでfilter_inputを使うように言われています。

    if (filter_input(INPUT_GET, 'func') && filter_input(INPUT_GET, 'get_data')) {

    ...にしています。

    デバッグ環境の作り方を知りたいです。

    キャンセル

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

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

関連した質問

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