【php・Ajax・mysql】Webtodoリスト完成~はじめてjs・php・Ajax・mysqlを連携させ、わかったこと・わからなかったこと~
【今回の紹介】
簡易なWebアプリを作ってみたいということから、
Webtodoリストを作成しました。
その振り返りとメモを兼ねて紹介します。
【内容】
■当初の目的
①Webアプリ作成の全体像をつかむ
①-①汎用的な機能(登録・変更・削除・検索)を作成してみる
①-②なんらかのデータをDBと連携するという流れをつかむ
②Ajaxの活用の幅を広げたい
②-①DBと連携した時にどのようなPGの組み方になるのか
②-②他言語との連携してみたい
■実績
①Webアプリ作成の全体像をつかむ
→定性的だけど、なんとなくつかめた
①-①汎用的な機能(登録・変更・削除・検索)を作成してみる
→すべての機能実装完了
①-②なんらかのデータをDBと連携するという流れをつかむ
→追加したリスト情報をDBと連携完了
②Ajaxの活用の幅を広げたい
②-①DBと連携した時にどのようなPGの組み方になるのか
Ajax→php→mysql→xml→Ajaxと言う流れを実感
②-②他言語との連携してみたい
→phpと連携
■わかったこと
①AjaxとDB連携の流れ
②同一ページ内でいろいろできる(登録・変更・削除・検索)
→送信ボタンを押して画面遷移してというのはいらない。
追加ボタンや追加したリスト名をダブルクリックすれば、
裏でAjaxがはしり、DBへの登録が行うことができる
また、DBからの値をうけとり、
画面上ではjavascriptが動的に表示を行う事もできる
③当たり前だけど、HTTP通信がステートレスな通信であることを痛感
→当然DBからの登録処理・読み込み処理が実装されなければ、
javascriptでいくら動的にリストを追加しても、更新(F5)を
押せば、入力情報はなくなる。
だからHTTP通信でデータを保存するには、
①ブラウザのキャッシュを使用したセッション管理
②DBとの連携
③外部ファイルへの書き込み・読み込み
というような手段をとることが整理できた。
※ちなみに今回は②を使用した
■わからなかったこと
①ajaxとDB連携の流れの詳細の部分
→具体的に言うと、xmlhttprequestによるpost後のphpからのレスポンスの受け取り方の部分。
、
phpからDB取得(レスポンス)をうまくうけとることができず、
なくなくxmlに変換して受け取ったけど、
本当にxmlに変換する方法しかないのか
ちょっと調べたらJSONというものもあるようだし、、
そこらへんがまだまだわからない部分なので要確認。
②jqueryでどのくらい便利になるのかって部分
今回は、jqueryは使用しなかったけど(最初は自分の理解のために未使用にした)
やたら検索するとでてくる。というか、問題が起こった時の解決方法とかも、jquery
だとこうすればよいという形で、jqueryのみの解決法を記載する場合が多かった。
javascriptにも当初よりかは馴れてきたので、
今後は、jqueryにも手を伸ばす必要があるかもしれない。
③PHPでなにができるか。
PHP自体を学習したことがなく、
・セッション管理
・dbとの連携
する印象しかない。
サーバサイドの言語としてもっといろいろできるのかなー
と思いながら、、、でした
【参考ソース】
メイン画面(css)
li{ list-style-type:decimal; font-weight:bolder; margin-top:0.5em; margin-left:0.5em; } #input{ margin-top:2em; height:40%; border-bottom:2px #000000 solid; } #serch{ float:left; } #frame_toDo{ float:left; height:90%; width:30%; border-right:2px #000000 solid; } #frame_Doing{ float:left; height:90%; width:30%; border-right:2px #000000 solid; } #frame_Done{ float:left; height:90%; width:30%; }
メイン画面
<!--////////////////////////////// //↓画面デザイン部分////////////// ////////////////////////////////--> <html> <head> <link rel="stylesheet" type="text/css" href="style.css"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <body> <div id="input"> <h3>追加</h3> <select onChange="select_option=this.options[this.selectedIndex].innerHTML"> <option></option> <option value="hight"> 優先度 高</option> <option value="nomal"> 優先度 中</option> <option value="low"> 優先度 低</option> </select> <input type="text" value="" id="add_text"> <input type="button" value="追加" id="button" onclick="add_list()"> <div id="serch"> <h3>検索</h3> <select onChange="serch_input(select_serch=this.options[this.selectedIndex].innerHTML)"> <option></option> <option value="doing_t">実行中タスク</option> <option value="done_t">完了タスク</option> </select> </div> <div id="serch_result"> </div> </div> <div id="frame_toDo"> <h1 id="h1_ToDo" onDblClick="allDel_li(this)">To Do</h1> <ul id="ul_toDo"></ul> </div> <div id="frame_Doing"> <h1 id="h1_Doing" onDblClick="allDel_li(this)";>Doing</h1> <ul id="ul_Doing"></ul> </div> <div id="frame_Done"> <h1 id="h1_Done" onDblClick="allDel_li(this)">Done</h1> <ul id="ul_Done"></ul> </div> <!--////////////////////////////// //↑画面デザイン部分////////////// ////////////////////////////////--> <?php /*////////////////////////////// //↓php・javascript処理部分// ////////////////////////////////*/ /*////////////////////////////// //レコードが存在するか判定処理// ////////////////////////////////*/ $mysqli=new mysqli('localhost','sa','qwertyuiop@1','db_01'); if($mysqli->connect_error){echo "DB接続できませーん";} $stmt=$mysqli->prepare("SET NAMES utf8"); $stmt->execute(); $stmt=$mysqli->prepare("select id from t_01 order by id desc limit 1 ") or exit("error"); $stmt->execute(); $stmt->bind_result($result_lastid); $stmt->fetch(); $last_id=$result_lastid; $last_id=$last_id+1; ?> <?php echo <<<EOM <script Language="JavaScript" type="text/javascript"> var count=1; var index=$last_id; var index_cheak=/[0-9]/; if(index_cheak.test(index)==true){count=$last_id;} /*////////////////////////////// /////////読み込み処理/////////// ////////////////////////////////*/ window.onload=d_road; function d_road(){ var url="d_load.php"; var httpobj =createHttpRequest(); httpobj.onreadystatechange = function() { if (httpobj.readyState == 4) { alert(httpobj.statusText); result_value=httpobj.responseXML; <!--DB取得データをdomに流し込む処理に渡す--> d_load_output(result_value); } }; httpobj.open("POST",url); httpobj.setRequestHeader('Pragma', 'no-cache'); httpobj.setRequestHeader('Cache-Control', 'no-cache'); httpobj.setRequestHeader('If-Modified-Since', 'Thu, 01 Jun 1970 00:00:00 GMT'); httpobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); httpobj.send(null); } /*//////////////////////////////////////// ////DBから取得したxmlをDOMに流し込む処理// ////////////////////////////////////////*/ function d_load_output(xmldata){ var nodelist=xmldata.getElementsByTagName('list'); for(var i=0;i<nodelist.length;i++){ var id=nodelist[i].childNodes[0].childNodes[0].nodeValue; var name=nodelist[i].childNodes[1].childNodes[0].nodeValue; var category=nodelist[i].childNodes[2].childNodes[0].nodeValue; var list_text=document.createTextNode(name); var new_list=document.createElement("li"); new_list.appendChild(list_text); new_list.id=id; new_list.setAttribute("onDblClick","moveList(this)"); new_list.setAttribute("onmouseover","addcolor(this)"); new_list.setAttribute("onmouseout","defaultcolor(this)");; switch(category){ case "frame_toDo": document.getElementById("ul_toDo").appendChild(new_list); break; case "frame_Doing": document.getElementById("ul_Doing").appendChild(new_list); break; case "frame_Done": document.getElementById("ul_Done").appendChild(new_list); break; } } } /*////////////////////////////// /////////検索処理/////////////// ////////////////////////////////*/ function serch_input(val){ var result_value=""; var send_value1=val; var url="serch.php"; var httpobj =createHttpRequest(); httpobj.onreadystatechange = function() { if (httpobj.readyState == 4) { alert(httpobj.statusText); result_value=httpobj.responseXML; serch_output(result_value); } }; httpobj.open("POST",url); httpobj.setRequestHeader('Pragma', 'no-cache'); httpobj.setRequestHeader('Cache-Control', 'no-cache'); httpobj.setRequestHeader('If-Modified-Since', 'Thu, 01 Jun 1970 00:00:00 GMT'); httpobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); httpobj.send("send_value="+send_value1); } function serch_output(xmldate){ var div_serch_result=document.getElementById("serch_result"); if(div_serch_result.hasChildNodes){ div_serch_result.removeChild(div_serch_result.firstChild); } var table=document.createElement("table"); var tbody=document.createElement("tbody"); var nodelist=xmldate.getElementsByTagName('list'); for(var i=0;i<nodelist.length;i++){ var row=document.createElement("tr"); <!--DB取得データをテーブルobjに流し込む処理--> for(var k=0;k<4;k++){ var cell=document.createElement("td"); cell.innerHTML=nodelist[i].childNodes[k].childNodes[0].nodeValue; row.appendChild(cell); } tbody.appendChild(row); } table.appendChild(tbody); table.border=1; document.getElementById("serch_result").appendChild(table); } /*////////////////////////////// /////////リスト追加処理/////////// ////////////////////////////////*/ function add_list(){ var add_priority="("+select_option+")"; var add_text=document.getElementById("add_text").value; var list_text=document.createTextNode(add_text+add_priority); var new_list=document.createElement("li"); new_list.appendChild(list_text); new_list.id=count; /*"new_list"+*/ new_list.setAttribute("onDblClick","moveList(this)"); new_list.setAttribute("onmouseover","addcolor(this)"); new_list.setAttribute("onmouseout","defaultcolor(this)"); document.getElementById("ul_toDo").appendChild(new_list); send_db(new_list.id); count++; } /*////////////////////////////// /////////リスト移動処理/////////// ////////////////////////////////*/ function moveList(obj){ var ul_toDo=document.getElementById("ul_toDo"); var ul_Doing=document.getElementById("ul_Doing"); var ul_Done=document.getElementById("ul_Done"); <!--どのカテゴリ(todo or doing or done)にあるリストか判定する処理--> if("frame_toDo"==obj.parentNode.parentNode.id){ var clone=obj.cloneNode(true); ul_Doing.appendChild(clone); ul_toDo.removeChild(obj); send_db(clone.id); } else if("frame_Doing"==obj.parentNode.parentNode.id){ var clone=obj.cloneNode(true); ul_Done.appendChild(clone); ul_Doing.removeChild(obj); send_db(clone.id); } else{ send_db(obj.id); ul_Done.removeChild(obj); } } /*////////////////////////////// ///////リスト強調表示処理///// ////////////////////////////////*/ function addcolor(obj){ obj.style.color="#ff0000"; } function defaultcolor(obj){ obj.style.color="#000000"; } <!--カテゴリー名(todo or doing or done)をダブルクリックすると配下の全リストを削除する処理--> function allDel_li(obj){ var allDel_ul=obj.nextSibling.nextSibling; var allDel_li=obj.nextSibling.nextSibling.childNodes; for(var i=allDel_li.length-1;i>=0;i--){ allDel_ul.removeChild(allDel_li[i]); } } /*///////////////////////////////// //DB処理(登録・変更・削除処理)/// //移動後の親ノードIDにより処理分岐// //////////////////////////////////*/ function send_db(obj_id){ /*共通処理(obj.objのID.objのカテゴリの取得)*/ var obj=document.getElementById(obj_id); var obj_ParentId=obj.parentNode.parentNode.id; var send_text1=encodeURIComponent(obj_id); var send_text2=encodeURIComponent(document.getElementById(obj_id).firstChild.nodeValue); var send_text3=encodeURIComponent(obj.parentNode.parentNode.id); switch(obj_ParentId){ /*移動後の親nodeIdが"frame_toDo"ならば登録処理*/ case "frame_toDo": send_value=send_text1+","+send_text2+","+send_text3; var url="insert_db.php"; var httpobj =createHttpRequest(); httpobj.onreadystatechange = function() { if (httpobj.readyState == 4) { alert(httpobj.statusText); } }; httpobj.open("POST",url); httpobj.setRequestHeader('Pragma', 'no-cache'); httpobj.setRequestHeader('Cache-Control', 'no-cache'); httpobj.setRequestHeader('If-Modified-Since', 'Thu, 01 Jun 1970 00:00:00 GMT'); httpobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); httpobj.send("send_value="+send_value); break; /*移動後の親nodeIdが"frame_Doing"ならば変更処理*/ case "frame_Doing": send_value=send_text1+","+send_text2+","+send_text3; var url="update_db.php"; var httpobj =createHttpRequest(); httpobj.onreadystatechange = function() { if (httpobj.readyState == 4) { alert(httpobj.statusText); } }; httpobj.open("POST",url); httpobj.setRequestHeader('Pragma', 'no-cache'); httpobj.setRequestHeader('Cache-Control', 'no-cache'); httpobj.setRequestHeader('If-Modified-Since', 'Thu, 01 Jun 1970 00:00:00 GMT'); httpobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); httpobj.send("send_value="+send_value); break; /*移動後の親nodeIdが"frame_Done"ならば変更または削除処理*/ case "frame_Done": send_value=send_text1+","+send_text2+","+send_text3; var url="update_db.php"; var httpobj =createHttpRequest(); httpobj.onreadystatechange = function() { if (httpobj.readyState == 4) { alert(httpobj.statusText); } }; httpobj.open("POST",url); httpobj.setRequestHeader('Pragma', 'no-cache'); httpobj.setRequestHeader('Cache-Control', 'no-cache'); httpobj.setRequestHeader('If-Modified-Since', 'Thu, 01 Jun 1970 00:00:00 GMT'); httpobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); httpobj.send("send_value="+send_value); break; } } /*////////////////////////////// //xmlhttprequestobjの生成処理/// ////////////////////////////////*/ <!--xmlhttprequestobjの生成--> function createHttpRequest(){ try{ return new XMLHttpRequest(); }catch(e){} try{ return new ActiveXObject('MSXML2.XMLHTTP.6.0'); }catch(e){} try{ return new ActiveXObject('MSXML2.XMLHTTP.3.0'); }catch(e){} try{ return new ActiveXObject('MSXML2.XMLHTTP'); }catch(e){} return null; } </script> EOM ?> </body> </html>
登録処理
<?php header('Content-Type: text/html; charset=UTF-8'); $input=$_POST['send_value']; $inputs=explode(",",$input); $time=date("Y-m-d H:i:s"); $mysqli=new mysqli('localhost','sa','qwertyuiop@1','db_01'); if($mysqli->connect_error){echo "DB接続できませーん";} $stmt=$mysqli->prepare("SET NAMES utf8"); $stmt->execute(); $stmt=$mysqli->prepare("insert into t_01 values('$inputs[0]','$inputs[1]','$inputs[2]','0','$time')") or exit("error"); $stmt->execute(); $mysqli->close(); ?>
変更処理
<?php header('Content-Type: text/html; charset=UTF-8'); $input=$_POST['send_value']; $inputs=explode(",",$input); $time=date("Y-m-d H:i:s"); $mysqli=new mysqli('localhost','sa','qwertyuiop@1','db_01'); if($mysqli->connect_error){echo "DB接続できませーん";} $stmt=$mysqli->prepare("SET NAMES utf8"); $stmt->execute(); $stmt=$mysqli->prepare("select category from t_01 where id='$inputs[0]'") or exit("セレクト文失敗"); $stmt->execute(); $stmt->bind_result($result_category); $stmt->fetch(); $mysqli->close(); if($result_category=='frame_toDo' || $result_category=='frame_Doing'){ $mysqli=new mysqli('localhost','sa','qwertyuiop@1','db_01'); if($mysqli->connect_error){echo "DB接続できませーん";} $stmt=$mysqli->prepare("SET NAMES utf8"); $stmt->execute(); $stmt=$mysqli->prepare("update t_01 set category='$inputs[2]',update_time='$time' where id='$inputs[0]'") or exit("変更文に問題ありー"); $stmt->execute(); $mysqli->close(); }else{ $mysqli=new mysqli('localhost','sa','qwertyuiop@1','db_01'); if($mysqli->connect_error){echo "DB接続できませーん";} $stmt=$mysqli->prepare("SET NAMES utf8"); $stmt->execute(); $stmt=$mysqli->prepare("update t_01 set delflg='1' where id='$inputs[0]'") or exit("削除分に問題ありー"); $stmt->execute(); $mysqli->close(); } ?>
検索処理
<?php header('Content-Type: text/html; charset=UTF-8'); /*検索条件の取得*/ $value=$_POST['send_value']; /**/ $mysqli=new mysqli('localhost','sa','qwertyuiop@1','db_01'); if($mysqli->connect_error){echo "DB接続できませーん";} $stmt=$mysqli->prepare("SET NAMES utf8"); $stmt->execute(); /*検索条件の取得による分岐*/ if($value=="実行中タスク") $stmt=$mysqli->prepare("select id,name,category,update_time from t_01 where delflg=0 ") or exit("error"); else{ $stmt=$mysqli->prepare("select id,name,category,update_time from t_01 where delflg=1 ") or exit("error"); } $stmt->execute(); $stmt->bind_result($result_id,$result_name,$result_category,$result_time); /*///////////////////////////// //DB取得データをxmlデータに変換// ////////////////////////////////*/ header("Content-type: text/xml"); echo'<?xml version="1.0" encoding="utf-8" ?>'; echo '<lists>'; while($stmt->fetch()){ echo '<list>'; echo '<id>'.$result_id.'</id>'; echo '<name>'.$result_name.'</name>'; echo '<category>'.$result_category.'</category>'; echo '<updatetime>'.$result_time.'</updatetime>'; echo '</list>'; } echo '</lists>'; ?>
読み込み処理
<?php header('Content-Type: text/html; charset=UTF-8'); $value=$_POST['send_value']; $mysqli=new mysqli('localhost','sa','qwertyuiop@1','db_01'); if($mysqli->connect_error){echo "DB接続できませーん";} $stmt=$mysqli->prepare("SET NAMES utf8"); $stmt->execute(); $stmt=$mysqli->prepare("select id,name,category from t_01 where delflg=0 ") or exit("error"); $stmt->execute(); $stmt->bind_result($result_id,$result_name,$result_category); /*////////////////////////////// //DB取得データをxmlデータに変換// ////////////////////////////////*/ header("Content-type: text/xml"); echo'<?xml version="1.0" encoding="utf-8" ?>'; echo '<lists>'; while($stmt->fetch()){ echo '<list>'; echo '<id>'.$result_id.'</id>'; echo '<name>'.$result_name.'</name>'; echo '<category>'.$result_category.'</category>'; echo '</list>'; } echo '</lists>'; ?>