MVC は単なるデザイン パターンであり、かつてはサーバー ステートメントと HTML ステートメントを組み合わせた PHP であると考えられていましたが、実際にはフレームワークを必要とせず、オリジナルの JavaScript Ajax を使用するだけで MVC 用に設計できます。何も使っていないのでIE6との互換性は非常に強いです。まだ「[php] データベースの追加、削除、変更、クエリと PHP と JavaScript の相互作用」のページにあります(クリックするとリンクが開きます)。データベースの追加、削除、変更、およびクエリの内容を宣伝していただければ幸いです。ウェブサイト全体へのクエリ。
1. 基本目標
Web ページ全体の効果は次のとおりです。ユーザーがフォームを入力した直後に効果が有効になります。
2. 基本的な考え方
まず、テストデータベースにこのようなユーザー情報テーブルがあり、テーブルを作成するときに、それらのデータベースフィールドのエンコーディングが utf-8 であるかどうかに注意してください。インストール latin1 のデフォルトのエンコーディングは変更しません。変更しないと死ぬほど殴られ、中国語を保存できなくなります。
次に、Web ページのプロジェクト全体の構造は次のとおりです。
view.php では、Web ページの更新はなく、元の JavaScript Ajax を使用して、Web ページの対話を直接完了します。 V-C層。 C-M 層間の対話は、M 層のビジネス ロジック クラスにメソッドを導入する include ステートメントを通じて行われ、クラス パラメーターの転送によって完了します。
同時に、C 層と M 層の PHP は、URL を直接入力してアクセスすることを拒否します。 JSPやASPとは異なり、C層やM層はコンパイルされたJAVAファイルやC#ファイルであるため、一切アクセスできません。私たちもそれを守る必要があります。
3. 制作プロセス
1. View レイヤーはシンプルな View.php で、そのレイアウトは次のとおりで、言うことはありません。非常にシンプルな HTML レイアウトです。同時に、このページには次の点にご注意ください:
(1) フォーム送信アクションはすべて、対応する JavaScript をトリガーするボタンによってトリガーされます。
(2) 各コンポーネントの ID。後で JavaScript で使用されます。ユーザー情報テーブルと ID を変更するためのドロップダウン ボックスは、以下の Ajax スクリプトを通じて読み込まれます。
(3) レイアウトには、しばらくスクリプトを含むphpコードがありません。これは、誰でもレイアウトするのに便利です。サフィックス名を .html に変更すると、正常に実行できます。実際の View レイヤーとは何ですか?それだけです。サーバーコードは一切ありません。
すごいです実際、View レイヤー全体の本質は以下の JavaScript スクリプトにあります。ビュー レイヤーでは、Xajax プラグイン「[php]Xajax Helloworld」を使用する必要はありません (クリックするとリンクが開きます)。ネイティブ JavaScript で直接書かれています。 JQueryなどのフロントエンドフレームワークに比べてコード量は多いですが、覚えるのは簡単ではありません。 Ajax オブジェクトの作成から Ajax リクエスト ヘッダーの設定、Ajax テキストの処理までは自分で書かなければなりませんが、開発プロセス中はコピペだけで済みます。したがって、すべての Ajax インタラクティブ関数は類似していることがわかります。 ForAllUserInfo() 関数を取り上げて、V-C レイヤーが Ajax を介してどのように対話するかに焦点を当てます。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>用户信息表</title></head><body>用户信息表如下:<div id="result"></div><hr />插入数据<br />用户名:<input type="text" name="username" />密码:<input type="text" name="password" /><button onclick="insert()">GO!</button><hr />修改数据<br /><select id="userid" name="userid"></select><select name="rowname"> <option value="username">用户名</option> <option value="password">密码</option></select><input type="text" name="rowtext" /><button onclick="update()">GO!</button></body></html>
コントロール層のページはすべて、ビュー層の JavaScript 関数に対応しています。
たとえば、dbupdate.php は view.php の update() 関数に対応します。次の 2 つの文に対応します。
<script>//首先,本页面一加载就调用两个函数,加载本页。ForAllUserInfo();ForTotal();//创建Ajax对象,不同浏览器有不同的创建方法,其实本函数就是一个简单的new语句而已。function createXMLHttpRequest(XMLHttpRequest){ var XMLHttpRequest; if(window.XMLHttpRequest){ XMLHttpRequest=new XMLHttpRequest(); } else if(window.ActiveXObject){ try{ XMLHttpRequest=new ActiveXObject("Msxml2.XMLHTTP"); } catch(e){ XMLHttpRequest=new ActiveXObject("Microsoft.XMLHTTP"); } } return XMLHttpRequest;}function ForAllUserInfo(){ var XMLHttpRequest=createXMLHttpRequest(XMLHttpRequest); //指明相应页面 var url="dbselect.php"; XMLHttpRequest.open("POST",url,true); //这里没法解释,你所有JavaScript的请求头都这样写就对了,不会乱码 XMLHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); //对于dbselect.php,本view.php没有任何参数给你。 XMLHttpRequest.send(null); //对于返回结果怎么处理的问题 XMLHttpRequest.onreadystatechange=function(){ //这个4代表已经发送完毕之后 if(XMLHttpRequest.readyState==4){ //200代表正确收到了返回结果 if(XMLHttpRequest.status==200){ //那么id为result的div,就是整个dbselect.php页面了。 document.getElementById("result").innerHTML=XMLHttpRequest.responseText; } else{ //如果不能正常接受结果,你肯定是断网,或者我的服务器关掉了。 alert("网络连接中断!"); } } };}function ForTotal(){ var XMLHttpRequest=createXMLHttpRequest(XMLHttpRequest); var url="dbtotal.php"; XMLHttpRequest.open("POST",url,true); XMLHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); XMLHttpRequest.send(null); XMLHttpRequest.onreadystatechange=function(){ if(XMLHttpRequest.readyState==4){ if(XMLHttpRequest.status==200){ var total=parseInt(XMLHttpRequest.responseText); //先把修改ID的下拉列表清空 document.getElementById("userid").innerHTML=""; if(total>0){ for(var i=1;i<total+1;i++){ //javascript增加节点过程,数据库有多少项就填充多少个ID给用户修改。 var selectnode=document.createElement("option"); selectnode.value=i; selectnode.innerHTML=i; document.getElementById("userid").appendChild(selectnode); } } } else{ alert("网络连接中断!"); } } }; }function insert(){ //从输入框拿来插入数据的所有表单 var username=document.getElementById("username").value; var password=document.getElementById("password").value; //如果用户输入的值不为空,则执行Ajax if(username!=""&&password!=""){ var XMLHttpRequest=createXMLHttpRequest(XMLHttpRequest); var url="dbinsert.php"; XMLHttpRequest.open("POST",url,true); XMLHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); //这里View层的View.php需要发送两个参数给Controll层的dbinsert.php处理 XMLHttpRequest.send("username="+username+"&password="+password); XMLHttpRequest.onreadystatechange=function(){ if(XMLHttpRequest.readyState==4){ if(XMLHttpRequest.status==200){ //添加数据成功,则部分刷新View层的用户信息表与修改ID的下拉列表 ForAllUserInfo(); ForTotal(); } else{ alert("网络连接中断!"); } } }; } else{ alert("不得为空!"); }}//这里修改数据与insert()同理function update(){ var userid=document.getElementById("userid").value; var rowname=document.getElementById("rowname").value; var rowtext=document.getElementById("rowtext").value; if(userid!=""&&rowname!=""&&rowtext!=""){ var XMLHttpRequest=createXMLHttpRequest(XMLHttpRequest); var url="dbupdate.php"; XMLHttpRequest.open("POST",url,true); XMLHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); XMLHttpRequest.send("userid="+userid+"&rowname="+rowname+"&rowtext="+rowtext); XMLHttpRequest.onreadystatechange=function(){ if(XMLHttpRequest.readyState==4){ if(XMLHttpRequest.status==200){ ForAllUserInfo(); ForTotal(); } else{ alert("网络连接中断!"); } } }; } else{ alert("不得为空!"); }}</script>
フロントエンドから送信された 2 つのデータを取得した後、モデル層と対話してデータベース操作を完了します。データベースを変更すると、データベースは結果を返さないため、フロントエンドにはデータがありません。フロントエンドから送信されたパラメータを取得できない場合は、悪意のあるユーザーが URL を入力してこのページを異常に開いた可能性があります。レイヤー C とレイヤー M は通常は公開されていません。
var url="dbupdate.php";XMLHttpRequest.open("POST",url,true);
データの挿入にも同じ原理が適用されるため、詳細は説明しません。フロントエンドの insert() 関数に対応します
<?php include_once("db.php"); if(empty($_REQUEST["userid"])){ header("Content-type: text/html; charset=utf-8"); echo "请正常打开此页!"; } else{ $db=new db(); $userid=$_REQUEST["userid"]; $rowname=$_REQUEST["rowname"]; $rowtext=$_REQUEST["rowtext"]; $db->modify("update user set ".$rowname."='".$rowtext."' where id=".$userid.";"); }?>
このページは、データ ドロップダウン リストを変更するときに、データベース内にある結果の数をクエリするために使用されます。ユーザーに ID の数を指定する必要があります。
view.php の ForTotal() 関数に対応します。このページには結果が返されました。したがって、dbtotal.php は、echo を使用して結果を出力します。フロントエンドは、
<?php include_once("db.php"); if(empty($_REQUEST["username"])){ header("Content-type: text/html; charset=utf-8"); echo "请正常打开此页!"; } else{ $db=new db(); $username=$_REQUEST["username"]; $password=$_REQUEST["password"]; $db->modify("insert into user(username,password) values ('".$username."','".$password."');"); }?>
このページはユーザーに表示する必要があるため、保護する必要はありません。
var total=parseInt(XMLHttpRequest.responseText);
このページは実際には dbtotal.php と同じですが、テーブルを構築し、それをフロントエンド View.php の ForAllUserInfo() に送信します。 ForAllUserInfo() によって取得されるデータは、実際には HTML テキストの一部であり、.innerHTML を介して直接配置できます。
<?php include_once("db.php"); $db=new db(); $total=$db->getTotal(); echo $total;?>
このページで HTML と PHP コードを混在させることができない強迫性障害の患者さんには、すべての HTML コードをエコー出力に変換してください。
3. モデル層
この層のすべてのメソッドは、C 層ページと対応関係を持ちます。
首先都公用一个数据库连接函数。之后各自在方法中调用,最后各自查询完毕则关闭这个连接。
然后,可以注意到上面的Controll层的dbupdate.php与dbinsert.php公用此类的一个方法。这主要是考虑到,都是传递一个SQL语句过来,然后没有返回结果,因此可以合在一起了。而查询数据库的所有数据与查询数据库的数据数量的返回结果是不同的,因此分开两个方法。
<?phpfunction createCon(){ //数据库的地址是localhost:3306,数据库用户名(第二项)是root,数据库密码(第三项)是root $con=mysql_connect("localhost","root","root"); if(!$con){ die("连接失败!"); } //要操作test数据库 mysql_select_db("test",$con); //防止乱码 mysql_query("set names utf8;"); return $con;}class db{ public function getAllUserInfo(){ $con=createCon(); $result=mysql_query("select * from user;"); //如果查询的结果多,就放到一个二维数组里面,返回给Controll层 //Controll层再对这个二维数组一一处理。 //起始这个二维数组不就相当于JSP中的ArrayList吗?^_^ $userList=array(); for($i=0;$row=mysql_fetch_array($result);$i++){ $userList[$i]['id']=$row['id']; $userList[$i]['username']=$row['username']; $userList[$i]['password']=$row['password']; } mysql_close($con); return $userList; } public function getTotal(){ $con=createCon(); $result=mysql_query("select count(*) as total from user;"); //如果返回结果只有一个,那就直接这样取数据。 $row=mysql_fetch_array($result); mysql_close($con); return $row['total']; } public function modify($sql){ //对于那些传sql过来没有返回结果的方法,归纳到同一类 $con=createCon(); mysql_query($sql); mysql_close($con); }}?>
上面的制作过程最好合在一起看,反正我只能这样分层贴了。V-C,C-M一直在交互,从未被割裂,根本停不下来。对比与《【php】数据库的增删改查和php与javascript之间的交互》(点击打开链接)这个以MODEL1模式创作的工程,页面虽然增多,但是模块更加地清晰。
反正MVC仅仅是一种设计模式、设计思想而已,在PHP同样也能够实现。在JSP对这种模式的吹嘘是言过其实了,主要是JSP的部分创作者,不停地对于框架的使用,而忘记了这门语言的本质。
我觉得这个例子,再次证明了语言只是思想表达的载体。无插件无框架,纯HTML+CSS与纯JavaScript加PHP就能够实现,兼容IE6。如果你打包一样,放上防注入函数,完全可以成为自己的框架的。
对比与JSP与ASP,我在写PHP的时候更加舒服,告别了MyEclipse/Eclipse与Visual Studio的卡爆,用着早已被批得一毛不是Dreamwaver,甚至还可以用记事本写着网页,半点不卡。一台垃圾配置的Winxp就能够创造出好的网站。关键是你的语言基本功问题了。少做点喷子,多做点工程。多接触几门编程语言。