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>
感想
今回の実装では、非常にシンプルなものを作りました。セキュリティー面での考慮はあまり考えずにつくりましたので、気になる方は、独自で対策をしてみてください。