jQuery ajax ボタンを押すとごとに次のデータ数件を表示する
実装概要
データの一覧を表示しますが、一般的なものは、例えば、1ページ目に、20件を表示して、ページの下部に、1・2・3・4… [最後] のように、次の20件ごとの番号にリンクしています。今回は、このような形式ではなく、ページの下部に、ボタンを設置し[次の20件]のように、ボタンを押すごとに、データが非同期で追加されていくようにします。また、元に戻すことのできるように[リセット]ボタンを設置します。

まずはデータベースの準備
準備するデータは、なんでもよいのですが、検証の為、とりあえず、100件以上位はあったほうがよいかもしれません。
・テーブル作成 data_01テーブル
id bigint(20) NOT NULL AUTO_INCREMENT,
title varchar(30) NOT NULL,
date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
・挿入するデータ
(‘SumiDaiNET テストデータ’),
(‘SumiDaiNET テストデータ’),
(‘SumiDaiNET テストデータ’),
(‘SumiDaiNET テストデータ’),
(‘SumiDaiNET テストデータ’),
(‘SumiDaiNET テストデータ’),
(‘SumiDaiNET テストデータ’),
(‘SumiDaiNET テストデータ’),
(‘SumiDaiNET テストデータ’),
(‘SumiDaiNET テストデータ’);
とりあえず、10件分の挿入ですが、実際は、100件ほどあったほうがよいので、コピペして、挿入箇所だけ複製する、又は、クエリを繰り返すなどして、挿入データを増やしてください。
データベースの準備が完了したら、db.phpにMySQLに接続情報を記載します。それをあとで読み込んで使うようにします。(このあたりは、host dbname $user $password の部分は、環境にあわせて、変更してください。)
db.php
<?php
function db_connect(){
$dsn = 'mysql:host=localhost;dbname=sample;charset=utf8';
$user = 'root';
$password = 'japan';
try{
$dbh = new PDO($dsn, $user, $password);
return $dbh;
}catch (PDOException $e){
print('Error:'.$e->getMessage());
die();
}
}
?>
index.phpの解説
まずは、上部のPHPコードから解説します。ここで、db.phpの接続情報を読み込み、接続します。ページが開かれると、変数$offset = 0 ,$limit = 25 で、sqlクエリのデータにLIMIT句をつけて、0の次から、25件を上限として取り出します。また、ボタンに、残りの件数を表示することから、データのトータル件数をSQL_CALC_FOUND_ROWSを使い取得し、25を差し引きます。(25件は表示されている為)。
<?php
require_once("db.php");
$dbh = db_connect();
$offset = 0;
$limit = 25;
try{
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT SQL_CALC_FOUND_ROWS id, id, title, date FROM data_01 LIMIT $offset, $limit";
$stmt = $dbh->query($sql);
$data = $stmt->fetchAll();
$stmt = $dbh->query('SELECT FOUND_ROWS()');
$data['count'] = $stmt->fetch(PDO::FETCH_ASSOC);
$data['count'] = $data['count']['FOUND_ROWS()']-$limit;
}catch (PDOException $e){
print('Error:'.$e->getMessage());
die();
}
?>
次に、javascriptの解説です。大きくわけて、3つの処理があります。上から順番に、ページを開いたときの表示、[次へ]のボタンと[リセット]ボタンを押したときの処理の3つに分かれます。特にコアな部分は、[次へ]のボタンを押したときのajaxでの処理で、外部のget_data.phpに変数offsetの値をPOSTで引き渡して、get_data.phpで、取得した次の件数の25件を取得します。
<script>
$(document).ready(function(){
var set = 25;
var ck = 0; //[次へ]のクリックの回数
var total = <?=$data['count']?>; //残りの件数
if(set + total > set){ //件数が25件よりも小さい場合
$('#total').html(total+'件'); //残り件数の表示
$('#set').html(set+'件'); //件数の表示
$('#reset').hide(); //[リセット]ボタンを隠す
}else{ //件数が25件よりも大きい場合
$('#more').hide(); //[次へ]の表示ボタンを隠す
$('#reset').hide(); //[リセット]ボタンを隠す
}
$('#more').click(function(){ //[次へ]の件数表示ボタンを押したときの処理↓
$('#reset').show(); //[リセット]ボタンの表示
ck ++;
offset = set * ck;
if(total >= 0){
total -= set;
}
if(total < set){
$('#set').html(total+'件');
}
$.ajax({
url: 'get_data.php', //送信先
type: 'POST',
data: { 'offset': offset },
timeout: 10000,
dataType: 'text'
})
.done(function( data ) {
//alert("確認" + data);
$('#add').append(data); //#addに追加
if(total <= 0){ //#totalの書き換え
$('#total').text('0件');
}else{
$('#total').text(total+'件');
}
});
if(total <= 0){
$('#more').hide();
}
return false;
});
$('#reset').click(function(){ //[リセット]の件数表示ボタンを押したときの処理↓
ck = 0;
total = <?=$data['count']?>;
$('#more').show();
$('#reset').hide();
$('#set').html(set+'件');
$('#add').empty();
$('#total').text('<?=$data['count']?>件');
});
});
</script>
<?php foreach ($data as $key => $value){ ?>
<?=$value['id'] ?><?=$value['title'] ?><?=$value['date'] ?><br>
<?php } ?>
<div id="add"></div>
<button id="more" type="button" class="btn btn-default"> >> <?php if (isset($data)){ ?>次の<span id="set"></span>表示 <?php } ?> (あと <?php if (isset($data)){ ?> <span id="total"></span> <?php } ?>) </button>
<a href="#top"><button id="reset" type="button" class="btn btn-default">リセット</button></a>
get_data.phpの解説
こちらのファイルは、index.phpよりajaxで呼びだしているわけですけど、見て分かるように、受け取ったデータをLIMIT句に挿入して、データの取得件数の開始場所をずらしいてるだけですので、ぼぼindex.phpと同じものになります。
<?php
require_once("db.php");
$dbh = db_connect();
$offset = $_POST['offset'];
$limit = 25;
try{
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT SQL_CALC_FOUND_ROWS id, id, title, date FROM data_01 LIMIT $offset, $limit";
$stmt = $dbh->query($sql);
$data = $stmt->fetchAll();
$stmt = $dbh->query('SELECT FOUND_ROWS()');
$data['count'] = $stmt->fetch(PDO::FETCH_ASSOC);
$data['count'] = $data['count']['FOUND_ROWS()']-$limit;
}catch (PDOException $e){
print('Error:'.$e->getMessage());
die();
}
?>
<?php foreach ($data as $key => $value){ ?>
<?=$value['id'] ?><?=$value['title'] ?><?=$value['date'] ?><br>
<?php } ?>
<div id="add"></div>
感想
今回の実装では、非常にシンプルなものを作りました。セキュリティー面での考慮はあまり考えずにつくりましたので、気になる方は、独自で対策をしてみてください。