はじめに
今までjavascriptのライブラリといえばjQuery一辺倒でjQueryを使ってきました。世間的には、Vue.jsとかReact等のjavascriptライブラリが脚光を浴びているようです。jQueryは使い慣れていますし、ある意味枯れて安定しているとも言えますので、当面使い続けるとは思いますが、そろそろvue.jsを勉強しよかと思い、重い腰を上げて少し学習しました。どうせなら、本業であるサーバーサイド側のPHPやデータベースmariaDB/mySQLとの連携をテーマとして、フロントのHTMLファイルから、Vue.jsを経由して、非同期でサーバーサイド側のPHPファイルを操作し、データベースを制御するWEBアプリケーションを題材として本記事をまとめてみました。本WEBアプリケーションは、CSSテンプレートであるBootstrapを用いてCSSの記述を省略化し、vue.jsでデータベースにデータを登録・更新・削除したり、一覧表示するものです。
作成するファイル(HTML,javascript,PHP)
test1.htmlファイルをフロント側として、ajax.js、サーバーサイド側のPHPファイル select_all.php、insert.phpを作成します。
一覧表示
はじめに下画像のような一覧表示を実現してみます。HTMLファイルtest1.htmlからJSファイルのajax.jsを呼びだし、ajax.jsからPHPファイル select_all.phpを呼び出して、以下のような一覧表示を実現することになります。
データベース
phpmyadminでmariaDB/mySQLに、このような構造のテーブルを準備します。フィールドとして、id 連番、name 名前、email メールアドレスのみのシンプルなテーブルです。
SQLを記載しておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
CREATE TABLE `user3` ( `id` int(11) NOT NULL, `name` varchar(255) NOT NULL, `email` varchar(255) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; INSERT INTO `user3` (`id`, `name`, `email`) VALUES (101, '山田太郎', 'tarou@yamada.com'), (102, '山田次郎', 'jirou@yamada.com'), (103, '山田三郎', 'saburou@yamada.com'); ALTER TABLE `user3` ADD PRIMARY KEY (`id`); ALTER TABLE `user3` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=104; |
一覧表示のHTMLファイル
HTMLファイルを記載します。test1.htmlとします。CSSの記載を省略して、見栄えを整えるために、Bootstrapのスターターテンプレートを利用します。https://getbootstrap.jp/docs/5.0/getting-started/introduction/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
<!doctype html> <html lang="ja"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <title>Vue.jsを使ったAJAX通信(PHP,mariaDB)</title> </style> </head> <body> <div class="container" id="vueApp"> <h1>Vue.jsを使ったAJAX通信</h1> <div id="select_all"> <table class="table"> <thead> <tr> <th scope="col">#</th> <th scope="col">name</th> <th scope="col">email</th> <th scope="col"></th> </tr> </thead> <tbody> <tr v-for="row in allData"> <td>{{ row.id }}</td> <td>{{ row.name }}</td> <td>{{ row.email }}</td> <td></td> </tr> </tbody> </table> </div> </div> <script src="ajax.js"></script> <!-- Optional JavaScript; choose one of the two! --> <!-- Option 1: Bootstrap Bundle with Popper --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js"></script> <!-- Option 2: Separate Popper and Bootstrap JS --> <!-- <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js"></script> --> </body> </html> |
vueApp要素が後述するvueの領域になり、<div id=”vueApp”>~</div>がvueの操作領域に置かれます。
一覧表示のjavascriptファイル
el:’#vueApp’で<div id=”vueApp”>範囲がこのvueの管轄領域にあることを定義しています。
allData:” として、変数allDataを初期化しています。
関数 fetchAllData:function() を定義しています。
axios.postとして、select_all.phpにPOST通信を行っています。一覧表示は、フロント側から送るデータはありませんので、第二引数は空となっています。
axiosの通信が成功した場合、application.allData = response.data;として、PHPファイルのSELECT結果が配列で格納されます。
HTMLファイル内の、row in allDataとして、SELECT結果の配列をリスト表示することになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
var application = new Vue({ //<div id="vueApp">範囲がこのvueの管轄領域にあることを定義 el:'#vueApp', //dataは vueの中で使われる変数 data:{ allData:'', }, methods:{ fetchAllData:function(){ // do axios.post('select_all.php',{ }).then(function(response){ //allDataにphpファイルSELECTの結果が配列で格納される application.allData = response.data; }); }, }, created:function(){ this.fetchAllData(); } }); |
一覧表示のPHPファイル
ajax.js から呼び出される一覧表示のためのPHPファイルselect_all.phpを記述します。単純に、mariaDB/mySQLに接続して、テーブル情報を配列に格納しています。JSON形式で出力します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?php $conn = mysqli_connect("localhost", "root", "", "sample"); if($conn){ }else{ echo "データベースに接続できません"; } $result = mysqli_query($conn, "SELECT `id`, `name`, `email` FROM `user3` ORDER BY id DESC"); if(mysqli_num_rows($result) == 0){ echo "レコードが有りません"; } while($row = mysqli_fetch_assoc($result)){ $data[] = $row; } //値をjson形式で出力 echo json_encode($data); ?> |
データの登録
HTMLファイル
登録フォームをbootstrapのテンプレートhttps://getbootstrap.jp/docs/5.0/components/modal/を利用し、修正して利用します。HTMLファイル test1.html に以下の登録フォームと登録フォームを表示させるボタンを追加します。なお、モーダルウインドウの開閉は、vue.js側から制御しますので、
.modal{display: block;}
.insert-error{display: none;}
</style>
としておきます。また、エラー表示箇所もデフォルト非表示とします。bootstrapにあったclass fadeは消しておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<button type="button" class="btn btn-primary" @click="insertModal = true"> 登録 </button> <!-- Modal --> <!--<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">--> <div v-if="insertModal"> <!--<div class="modal fade" id="exampleModal" tabindex="-1">--> <div class="modal" id="exampleModal" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="exampleModalLabel">登録フォーム</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @click="insertModal = false"></button> </div> <div class="modal-body"> <form action="#" method="POST" enctype="multipart/form-data" autocomplete="off"> <div class="alert alert-dismissible alert-danger insert-error"> 登録内容に問題があります </div> <div class="mb-3"> <label for="exampleFormControlInput1" class="form-label">name</label> <input type="text" name="name" id="name" class="form-control" placeholder="名前を入力してください" v-model="name"> </div> <div class="mb-3"> <label for="exampleFormControlInput1" class="form-label">email</label> <input type="text" name="email" id="email" class="form-control" placeholder="emailを入力してください" v-model="email"> </div> <div class="mb-3"> <button type="button" name="submit" class="btn btn-primary" @click="insertData">登録する</button> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id="btn-close" @click="insertModal = false">閉じる</button> </div> </div> </div> </div> </div> |
データ登録のためにajax.jsを修正
javascriptファイルajax.jsを修正します。 v–if ディレクティブのinsertModalを初期値falseとします。vue内で使う変数name、emailを初期化する必要があります。ボタン登録するをクリックすると@click=”insertData”として、関数insertDataが発火します。
v-model
ディレクティブとして、form内に、部品nameとemailがあります。axios.postとして、insert.phpにPOST通信を行っています。データ登録は、フロント側から送るデータはnameとemailがありますので、第二引数はname:this.name,email:this.emailとします。
axiosの通信が成功した場合、fetchAllData関数を呼び出して、新たに登録されたデータを含むSELECT結果を再描画します。フォーム内の部品name,emailを初期します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
var application = new Vue({ //<div id="crudApp">範囲がこのvueの管轄領域にあることを定義 el:'#vueApp', //dataは vueの中で使われる変数 data:{ insertModal: false, allData:'', name:'', email:'', }, methods:{ fetchAllData:function(){ // do axios.post('select_all.php',{ }).then(function(response){ //allDataにphpファイルSELECTの結果が配列で格納される application.allData = response.data; }); }, //以下Insert insertData:function(){ axios.post('insert.php',{ name:this.name, email:this.email }).then(function(response){ console.log(response.data.message); if(response.data.message == "success"){ alert("登録しました"); application.fetchAllData(); application.name = ""; application.email = ""; }else{ alert(response.data.message); } }); }, }, created:function(){ this.fetchAllData(); } }); |
データ登録するPHPファイル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?php $conn = mysqli_connect("localhost", "root", "", "sample"); if($conn){ }else{ echo "データベースに接続できません"; } $received_data = json_decode(file_get_contents("php://input")); $name = $received_data -> name; $email = $received_data -> email; if( !empty($name) && !empty($email) ){ if(preg_match('/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/iD', $email)){ $sql2_query = "INSERT INTO `user3`(`name`, `email`) VALUES ('$name', '$email')"; $sql2 = mysqli_query($conn, $sql2_query); if($sql2){ $message = "success"; }else{ $message = "問題があります。"; } }else{ $message = "emailアドレスとして適切ではありません"; } }else{ $message = "未記入の項目があります"; } $output = array( 'message' => $message ); echo json_encode($output); ?> |