Posted at

【jQuery】PHP/Ajax/MySQL を利用した非同期通信を行う


実装内容


  • productsテーブルを作成する。(カラムはid, name, priceの3つ)

  • 一覧に常にレコード全件が表示される

  • 特定のidからnameとpriceを取り出して表示する

  • 新しくレコードを追加して、一覧に追記する

  • レコード追加前に確認メッセージを表示する


AjaxとJSON

こちらの記事がわかりやすいです!


初心者目線でAjaxの説明



Ajax


  • Asynchronous JavaScript + XML

  • JavaScript組み込みクラスであるXMLHttpRequestによる非同期(Asynchronous)通信のこと


JSON


  • JavaScript Object Notation

  • データ形式の1つ

  • XMLに替わり、Ajaxで使われることが多い


ファイル構成

サーバはApache、データベースはMySQLを使用しました。

htdocsの下にajax_testディレクトリを用意し、その中に必要なファイルを作成します。

$ pwd

/usr/local/var/www/htdocs/ajax_test
$ ls
ajax_test.html ajax_test_add.php ajax_test_show_all.php
ajax_test.js ajax_test_show.php


テーブルの作成

既存のデータベースdb1にproductsテーブルを追加しました。

作成済みのテーブルは、SHOW CREATE TABLEコマンドで作成時のクエリを確認できるので便利です。

Tableカラムにテーブル名、Create Tableカラムに作成時のクエリが表示されます。(ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8は、テーブル作成時には記述していません。)

mysql> use db1;

SHOW CREATE TABLE products;

Create Tableの値

CREATE TABLE `products` (

`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
`price` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8

適当にレコードを作成しておきます。

mysql> INSERT INTO products(name, price) VALUES('りんご', 100), ('みかん', 80);

ちなみに、MySQLのコマンドラインは\cで入力キャンセルができます。(前までは\qを実行していて、コマンドラインから退出してました;)


MySQLのコマンドラインで入力をキャンセルする



HTML


ajax_test.html

<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8">
<!-- jQueryの読み込み -->
<title>Ajax、PHP、MySQLの連携</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<!-- 指定したidからレコード取得 -->
<div class="show_products">
IDを入力:<input id="id_number"><br>
<!-- 取得したレコードを表示 -->
<div id="result">
</div>
<!-- 送信ボタン -->
<button id="ajax_show">詳細ボタン</button>
</div>
<!-- レコード追加 -->
<div class="add_products">
<!-- 入力フォーム -->
商品名を入力:<input id="name"><br>
価格を入力:<input id="price"><br>
<!-- レコード追加後に入力内容を表示 -->
<div id="add_result">
</div>
<!-- 送信ボタン -->
<button id="ajax_add">追加ボタン</button>
</div>
<!-- レコード全件取得 -->
<!-- 追加したレコードも即時反映される -->
<table border="1" id="all_show_result">
<tr>
<th>id</th><th>商品名</th><th>価格</th>
</tr>
</table>
<script src="ajax_test.js"></script>
</body>
</html>


jQuery

勉強用なので、やたらとconsole.logが記述してあります。


ajax_test.js

$(function(){

// レコードを全件表示する
// 試しに関数にしてみただけ
function getAllData(){
$.ajax({
// 通信先ファイル名
url: "ajax_test_show_all.php",
// 通信が成功した時
success: function(data) {
// 取得したレコードをeachで順次取り出す
$.each(data, function(key, value){
// #all_show_result内にappendで追記していく
$('#all_show_result').append("<tr><td>" + value.id + "</td><td>" + value.name + "</td><td>" + value.price + "</td></tr>");
});

console.log("通信失敗");
console.log(data);
},

// 通信が失敗した時
error: function(){
console.log("通信失敗");
console.log(data);
}
});
}

// 関数を実行
getAllData();

// #ajax_showがクリックされた時の処理
// 指定したidのレコードを取得する
$('#ajax_show').on('click',function(){
$.ajax({
// リクエスト方法
type: "GET",
// 送信先ファイル名
url: "ajax_test_show.php",
// 受け取りデータの種類
datatype: "json",
// 送信データ
data:{
// #id_numberのvalueをセット
"id" : $('#id_number').val()
},
// 通信が成功した時
success: function(data) {
// 取得件数が1件のため、取得した情報を#result内にそのまま追加する
$('#result').html("<p>ID番号" + data[0].id + "は「" + data[0].name + "」です。<br>価格は「" + data[0].price+"円」です。</p>");

console.log("通信成功");
console.log(data);
},

// 通信が失敗した時
error: function(data) {
console.log("通信失敗");
console.log(data);
}
});

return false;
});

// #ajax_addがクリックされた時の処理
$('#ajax_add').on('click',function(){
// 確認メッセージを表示
// OKならtrue,キャンセルならfalseが代入される
var confirmResult = window.confirm("登録してもよろしいですか?");

if(confirmResult) {
$.ajax({
// 送信方法
type: "POST",
// 送信先ファイル名
url: "ajax_test_add.php",
// 受け取りデータの種類
datatype: "json",
// 送信データ
data: {
// #nameと#priceのvalueをセット
"name" : $('#name').val(),
"price" : $('#price').val()
},
// 通信が成功した時
success: function(data) {
$('#add_result').html("<p>" + data[0].name + "" + data[0].price + "円のデータを登録しました。</p>");

console.log("通信成功");
console.log(data);

// 一覧に追加したレコードを追記
$.each(data, function(key, value){
$('#all_show_result').append("<tr><td>" + value.id + "</td><td>" + value.name + "</td><td>" + value.price + "</td></tr>");
});
},

// 通信が失敗した時
error: function(data) {
console.log("通信失敗");
console.log(data);
}
});
}

return false;
});
});



こんな書き方も


getメソッド

通信の成功時のみ、実行されます。


ajax_test.js

function getAllData(){

$.get("ajax_test_show_all.php",
function(data){
$.each(data, function(key, value){
$('#all_show_result').append("<tr><td>" + value.id + "</td><td>" + value.name + "</td><td>" + value.price + "</td></tr>");
});

console.log("通信成功");
console.log(data);
}
);
}



doneメソッドとfailメソッド

メソッドチェーンを使います。


ajax_test.js

$('#ajax_show').on('click',function(){

$.ajax({
// リクエスト方法
type: "GET",
// 送信先ファイル名
url: "ajax_test_show.php",
// 受け取りデータの種類
datatype: "json",
// 送信データ
data:{
// #id_numberのvalueをセット
"id" : $('#id_number').val()
}
})

// 通信が成功した時
.done( function(data) {
$('#result').html("<p>ID番号" + data[0].id + "は「" + data[0].name + "」です。<br>価格は「" + data[0].price+"円」です。</p>");

console.log('通信成功');
console.log(data);
})

// 通信が失敗した時
.fail( function(data) {
console.log('通信失敗');
console.log(data);
});

return false;
});



レコード表示処理(全件)

コードの重複が多い・・・


ajax_test_show_all.php

<?php

// データベース接続
// $host = localhostで動かなければipアドレスを記載
$host = '127.0.0.1';
// データベース名
$dbname = 'db1';
// ユーザー名
$dbuser = 'user_name';
// パスワード
$dbpass = 'password';

// データベース接続クラス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 id, name, price FROM products";
// 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(
'id' => $row['id'],
'name' => $row['name'],
'price' => $row['price']
);
}

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



レコード表示処理(id検索の1件のみ)


ajax_test_show.php

<?php

// GETメソッドでリクエストした値を取得
$id = $_GET['id'];

// データベース接続
// $host = localhostで動かなければipアドレスを記載
$host = '127.0.0.1';
// データベース名
$dbname = 'db1';
// ユーザー名
$dbuser = 'user_name';
// パスワード
$dbpass = 'password';

// データベース接続クラス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 id, name, price FROM products WHERE id = ?";
// SQLをセット
$stmt = $dbh->prepare($sql);
// SQLを実行
$stmt->execute(array($id));

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

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

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


リクエストメソッドはGETを使用しているので、http://localhost/ajax_test/ajax_test_show.php/?id=41/でアクセスすると、[{"id":41,"name":"\u308a\u3093\u3054","price":100}]のようにレスポンスが返ってきます。

データ形式はもちろんJSONです。


レコード追加処理


ajax_test_add.php

<?php

// POSTメソッドでリクエストした値を取得
$name = $_POST['name'];
$price = $_POST['price'];

// データベース接続
// $host = localhostで動かなければipアドレスを記載
$host = '127.0.0.1';
// データベース名
$dbname = 'db1';
// ユーザー名
$dbuser = 'user_name';
// パスワード
$dbpass = 'password';

// データベース接続クラス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 = "INSERT INTO products(name, price) VALUES(?, ?)";
// SQLをセット
$stmt = $dbh->prepare($sql);
// SQLを実行
$stmt->execute(array($name, $price));

// 先ほど追加したデータを取得
// idはlastInsertId()で取得できる
$last_id = $dbh->lastInsertId();
// データ追加用SQL
// 値はバインドさせる
$sql = "SELECT id, name, price FROM products WHERE id = ?";
// SQLをセット
$stmt = ($dbh->prepare($sql));
// SQLを実行
$stmt->execute(array($last_id));

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

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

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


追加したばかりのレコードのidがどのように渡されているか、var_dump(array($last_id));を追記して確認できます。(内容はデベロッパーツールで確認できます。)

こんな感じで返ってきます。


ajax_test_add.php

array(1) {

[0]=>
string(2) "61"
}


参考記事


Ajaxを使ってデータベースのデータを非同期で取得する【Ajax+MySQL+PHP】