LoginSignup
22
27

More than 5 years have passed since last update.

Ajax処理とMySQLを使って、ページを更新せずにデータべ―スの読み書き

Last updated at Posted at 2018-11-12

動作の流れ

まず今回実現したい動作について説明します。

  1. HTMLのフォームに入力してEnterキーを押す image.png
  2. 入力内容をデータベースに挿入 image.png
  3. 入力内容をHTML要素として挿入 image.png

フォームの内容を入力したときのイベント

1のフォームに入力してEnterキーを押したときのイベント処理を考えていきます。

onメソッド

セレクタ.on('イベント',関数);とすると、
セレクタで指定したHTML要素に第1引数のイベントが発生したときに、第2引数の関数が実行されます。

セレクタ.イベント(関数);で、
clickイベントなどはonとだいたい同じように使うことができます。
しかし、このようなイベント名のメソッドは、onメソッドと違って、jQueryなどで動的に作成したHTMLタグに対しては動作してくれません。

今回はフォームの内容をリスト上で動的に追加するので、onメソッドで統一しておきます。

changeとsubmit

入力フォームに内容を入力してEnterキーを押したときに、2~4の処理を実行したいわけですが、どのイベントを使ったらいいのでしょうか。

フォームに関するイベントには
・changeイベント
・submitイベント
があります。

changeイベントはフォーム部品の状態が変化したときに発生します。
一方submitはフォームが送信されたときに発生します。

今回のページでは入力フォームが1つだけなので、Enterを押したらフォームが送信されます。
ですから、submitイベントがよさそうです。

ページ遷移したくない!

とりあえず、onメソッドでsubmitイベントがちゃんと発生するか調べてみます。
但し、"#new_todo_form"はform要素につけたIDです。

todo.js
$('#new_todo_form').on('submit', function(){
console.log("success");
/* 2~4の処理 */
});

実行すると
image.png

image.png

ページが更新されてしまいました!
formタグでページの遷移先は指定していないので、同じページが再読み込みされたのでしょう。

「新しいページにしなくていいから、そのままでいて・・・。」

そう思って、私はchangeメソッドでもいろいろ試したりしていたわけですが、実はたった1行書き加えるだけでよかったんですよね・・・。

return false;

これをonメソッドの第2引数の関数の末尾に書けば、ページ遷移を防ぐことができるのです。

データベースに挿入

onメソッドの第2引数の関数を作っていきます。
サーバーのデータベースに非同期でアクセスしたいので,
Ajax処理を利用していきます。

todo.js

  $('#new_todo_form').on('submit', function(){
    // idを取得
    var title = $('#new_todo').val();
    //ajax処理
    $.post('_ajax.php',{
      title: title,
      mode: 'create',
      token: $('#token').val()
    },function(res){
    /*3の処理*/
    });
  });

$.post(’データの送信先’,{key:data},functoin(res){});
とすると、formタグのmethod属性をpostにしたときと同じように
’データの送信先に’dataを送れます。
また、送信先の_ajax.phpで、echoなどで出力された内容が、送信先の処理が終わった後に実行される関数の引数resで受け取ることができます。

_ajax.phpの作成

_ajax.php

$todoApp = new \MyApp\Todo();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  try {
    $res = $todoApp->post();
    header('Content-Type: application/json');
    echo json_encode($res);
    exit;
  } catch (Exception $e) {
    header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
    echo $e->getMessage();
    exit;
  }
}

Todo.phpに記述したTodoクラスのメソッドpost()を呼び出すと、mode:createの場合に、データベースに新しくデータを挿入するcreateメソッドを呼ぶようにしています。
返す値は扱いやすいようにjsonコードにしておきます。

createメソッドの作成

todo.php

  private function _create(){
    if(!isset($_POST['title'])|| isset($_POST['title']) === ''){
      throw new \Exception('[create] title not set!');
    }

    $sql = "insert into todos (title) values (:title)";
    $stmt = $this->_db->prepare($sql);
    $stmt->execute([':title' => $_POST['title']]);

    return ['id' => $this->_db->lastInsertId()];
  }

postで送信したデータを$_POST['key']で呼び出します。
フォームの内容が空じゃないかどうか調べて、throwで例外処理を発生させます。

フォームから受信したデータが空じゃなかったら、
insert文を使ってデータを挿入していきます。
プレースホルダーを使って出力します。
これはSQLインジェクション対策なのですが、XSS対策とSQLインジェクション対策で少し説明しているので、参考にしていただければ幸いです。

最後に追加した内容のIDを取得して、連想配列で返します。
これは_ajax.php上でjson形式に変換されます。

テンプレートをcloneメソッドで複製

入力データをHTML要素として挿入する時には、テンプレートがあって、属性値や、タグの中身にデータを入れるだけにしておくと便利そうですよね。

そこで、idex.php上にこのようなテンプレートを作っておきます。

index.php
 <li id="todo_templete" data-id="">
         <input type="checkbox" class="update_todo">
         <span class="todo_title"></span>
         <div class="delete_todo">x</div>
 </li>

テンプレートをセレクタで指定して、cloneメソッドを使うと、複製することができます。
複製した要素にattrメソッドやdataメソッド、textメソッドなどをデータを挿入していきます。
そして、prependメソッドでリストの先頭に複製した要素を挿しこみます。

todo.js
   function(res){
      //liを追加 index.phpのテンプレ―を複製
      var $li = $('#todo_templete').clone();
      $li
      .attr('id','todo_' + res.id)
      .data('id',res.id)
      .find('.todo_title').text(title);
      $('#todos').prepend($li.fadeIn());
      $('#new_todo').val('').focus(); //空にしてfocusを当てて連続で入力可能に
   }

フォームに連続して入力できるようにしたいので、val('')でフォームの中身を空にして、focusを当てておきました。

22
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
27