搜尋
首頁後端開發php教程【php】利用原生态的JavaScript Ajax为php进行MVC分层设计,兼容IE6

MVC只是一种设计模式而已,一度被认为Model 1,也就是服务器语句与HTML语句杂糅的php,其实不用任何框架,仅仅利用原生态的JavaScript Ajax也可以对其进行MVC设计。由于什么都没有用,因此对IE6的兼容性是非常强的。还是《【php】数据库的增删改查和php与javascript之间的交互》(点击打开链接)那个页面的,对数据库增删改查的内容,希望各位能推广到整个网站。


一、基本目标

整个网页实现效果如下,用户输入完表单马上就有效果。


二、基本思想

首先,在test数据库中有一张这样的用户信息表,建表的时候注意检查一下那些数据库字段的编码是否是utf-8,一些Mysql在安装时候没有改默认的编码latin1的,不然一会儿你打死无法存中文。


然后,整个网页工程结构如下图:


在view.php中网页中不进行任何刷新,利用原生态的JavaScript Ajax,直接完成V-C层的交互。C-M层的交互通过include语句,引入M层的业务逻辑类中方法,通过类参数的传递完成。

同时,C、M层的php拒绝直接输入网址访问。这里不像JSP或者ASP,C层、M层都是编译之后的JAVA文件或者C#文件,根本就访问不了。我们还要对其进行保护。



三、制作过程

1、View层就一个简单的View.php,其布局如下,没什么好说的,非常简单的HTML布局。同时,注意,本页面:

(1)没有设置表单,所有表单提交的动作,通过button触发相应的JavaScript而触发。

(2)各个组件的ID,一会儿在JavaScript用到。其中用户信息表、修改ID的下拉框都是通过下面的脚本Ajax而加载的。

(3)布局中,包括一会儿的脚本在内没有任何php代码,便于各位布局。你把后缀名改成.html也能够正常运行。什么叫做真正的View层?这就是了,没有任何的服务器代码。

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>用户信息表</title>用户信息表如下:<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>

其实整个View层的精髓在于下面的JavaScript脚本。View层就无须使用到Xajax这个插件了,《【php】Xajax Helloworld》(点击打开链接)。直接用原生态的JavaScript写。虽然代码量比起JQuery等前端框架较多,记住不容易。从建立Ajax对象,设置Ajax请求头,处理Ajax文本都要自己写,但在开发过程中,只是复制粘贴而已。因此可以观察到,所有的Ajax交互函数都大同小易。拿ForAllUserInfo();这个函数来重点说明怎么V-C层怎么通过Ajax交互。

<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、Controll层

Controll层的页面都与View层中的JavaScript函数一一对应。

比如dbupdate.php就对应view.php中的update()函数。通过如下两句对应起来。

var url="dbupdate.php";XMLHttpRequest.open("POST",url,true);
(1)dbupdate.php

非常简单的页面,拿到前端送过来的两个数据,则进行与Model层的交互,完成数据库的操作。修改数据库,数据库是不会返回任何结果的,因此也没有什么数据给前端的。如果拿不到前端送过来的参数,那一定是恶意用户,通过输入网址非正常打开此页。C层M层一般是不给你打开的。

<?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.";");	}?>

(2)dbinsert.php

插入数据同样的道理了,不再赘述。对应于前端的insert()函数

<?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."');");	}?>
(3)dbtotal.php

这一页是用来查询数据库有多少条结果,我们在修改数据的下拉列表就要提供给用户多少个ID,给用户指定修改。

对应于view.php中的ForTotal()函数。这一页是有返回结果的。因此dbtotal.php就把这个结果用echo打印出来,前端通过:

var total=parseInt(XMLHttpRequest.responseText);
这一句中的XMLHttpRequest.responseText拿到,前端的JavaScript必须强制指明这是数字,否则则出现7+1=71的神运算。JavaScript把数字当字符串了,也没办法了,毕竟所有变量都是var。php则都是美元$。

这一页就无须保护了,毕竟肯定要给用户看的。

<?php include_once("db.php");	$db=new db();	$total=$db->getTotal();	echo $total;?>
(4)dbselect.php

这一页其实和dbtotal.php一样,不过变成了构造一个表格,送给前端View.php的ForAllUserInfo()。ForAllUserInfo()得到的数据其实一段HTML文本,直接通过.innerHTML放上去就可以了。

<?php include_once("db.php");	$db=new db();	$user=$db->getAllUserInfo();?>
"; }?>
ID 用户名 密码
".$user[$i]['id']." ".$user[$i]['username']." ".$user[$i]['password']."

这页有HTML打死都不能与PHP代码混在一起的强迫症患者,请自行把所有HTML的代码,给成echo输出,反正我就只能给出这样的一个方案了。


3、Model层

这一层的所有方法都与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就能够创造出好的网站。关键是你的语言基本功问题了。少做点喷子,多做点工程。多接触几门编程语言。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
超越炒作:評估當今PHP的角色超越炒作:評估當今PHP的角色Apr 12, 2025 am 12:17 AM

PHP在現代編程中仍然是一個強大且廣泛使用的工具,尤其在web開發領域。 1)PHP易用且與數據庫集成無縫,是許多開發者的首選。 2)它支持動態內容生成和麵向對象編程,適合快速創建和維護網站。 3)PHP的性能可以通過緩存和優化數據庫查詢來提升,其廣泛的社區和豐富生態系統使其在當今技術棧中仍具重要地位。

PHP中的弱參考是什麼?什麼時候有用?PHP中的弱參考是什麼?什麼時候有用?Apr 12, 2025 am 12:13 AM

在PHP中,弱引用是通過WeakReference類實現的,不會阻止垃圾回收器回收對象。弱引用適用於緩存系統和事件監聽器等場景,需注意其不能保證對象存活,且垃圾回收可能延遲。

解釋PHP中的__ Invoke Magic方法。解釋PHP中的__ Invoke Magic方法。Apr 12, 2025 am 12:07 AM

\_\_invoke方法允許對象像函數一樣被調用。 1.定義\_\_invoke方法使對象可被調用。 2.使用$obj(...)語法時,PHP會執行\_\_invoke方法。 3.適用於日誌記錄和計算器等場景,提高代碼靈活性和可讀性。

解釋PHP 8.1中的纖維以進行並發。解釋PHP 8.1中的纖維以進行並發。Apr 12, 2025 am 12:05 AM

Fibers在PHP8.1中引入,提升了並發處理能力。 1)Fibers是一種輕量級的並發模型,類似於協程。 2)它們允許開發者手動控制任務的執行流,適合處理I/O密集型任務。 3)使用Fibers可以編寫更高效、響應性更強的代碼。

PHP社區:資源,支持和發展PHP社區:資源,支持和發展Apr 12, 2025 am 12:04 AM

PHP社區提供了豐富的資源和支持,幫助開發者成長。 1)資源包括官方文檔、教程、博客和開源項目如Laravel和Symfony。 2)支持可以通過StackOverflow、Reddit和Slack頻道獲得。 3)開發動態可以通過關注RFC了解。 4)融入社區可以通過積極參與、貢獻代碼和學習分享來實現。

PHP與Python:了解差異PHP與Python:了解差異Apr 11, 2025 am 12:15 AM

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

php:死亡還是簡單地適應?php:死亡還是簡單地適應?Apr 11, 2025 am 12:13 AM

PHP不是在消亡,而是在不斷適應和進化。 1)PHP從1994年起經歷多次版本迭代,適應新技術趨勢。 2)目前廣泛應用於電子商務、內容管理系統等領域。 3)PHP8引入JIT編譯器等功能,提升性能和現代化。 4)使用OPcache和遵循PSR-12標準可優化性能和代碼質量。

PHP的未來:改編和創新PHP的未來:改編和創新Apr 11, 2025 am 12:01 AM

PHP的未來將通過適應新技術趨勢和引入創新特性來實現:1)適應云計算、容器化和微服務架構,支持Docker和Kubernetes;2)引入JIT編譯器和枚舉類型,提升性能和數據處理效率;3)持續優化性能和推廣最佳實踐。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版