AJAX在PHP中的简单使用
AJAX无疑是2005年炒的最热的Web开发技术之一,当然,这个功劳离不开Google。我只是一个普通开发者,使用AJAX的地方不是特别多,我就简单的把我使用的心得说一下。(本文假设用户已经具有Javascrīpt、HTML、CSS等基本的Web开发能力)
PHPChina 开源社区门户@4W&PwF3G X\;X'd
[ AJAX介绍 ]
Ajax是使用客户端脚本与Web服务器交换数据的Web应用开发方法。Web页面不用打断交互流程进行重新加裁,就可以动态地更新。使用Ajax,用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的Web用户界面。
异步Javascrīpt和XML(AJAX)不是什么新技术,而是使用几种现有技术——包括级联样式表(CSS)、Javascrīpt、XHTML、XML和可扩展样式语言转换(XSLT),开发外观及操作类似桌面软件的Web应用软件。
[ AJAX执行原理 ]
一个Ajax交互从一个称为XMLHttpRequest的Javascrīpt对象开始。如同名字所暗示的,它允许一个客户端脚本来执行HTTP请求,并且将会解析一个XML格式的服务器响应。Ajax处理过程中的第一步是创建一个XMLHttpRequest实例。使用HTTP方法(GET或POST)来处理请求,并将目标URL设置到XMLHttpRequest对象上。
当你发送HTTP请求,你不希望浏览器挂起并等待服务器的响应,取而代之的是,你希望通过页面继续响应用户的界面交互,并在服务器响应真正到达后处理它们。要完成它,你可以向XMLHttpRequest注册一个回调函数,并异步地派发XMLHttpRequest请求。控制权马上就被返回到浏览器,当服务器响应到达时,回调函数将会被调用。
[ AJAX实际应用 ]
PHPChina 开源社区门户h.?V.qp z6P
1. 初始化Ajax
Ajax实际上就是调用了XMLHttpRequest对象,那么首先我们的就必须调用这个对象,我们构建一个初始化Ajax的函数:
/**
D?WK_/O7o~;O0 * 初始化一个xmlhttp对象
D%}2C,@eLq;yD`^0 */
"F4bp!E9l%e$eE(C~j0function InitAjax()
:b@Z3G E7sb0{PHPChina 开源社区门户{XJ6r-Oby
var ajax=false;
+O Ri5l/dS'x0]0 try {
;E m i3N] vHRwY T0 ajax = new ActiveXObject("Msxml2.XMLHTTP");
;J)tE)n(Q9w7O3Z I0 } catch (e) { PHPChina 开源社区门户Oh1f0d;b:mg2F6y1Jzap
try {
q!y%sQ%U w0 ajax = new ActiveXObject("Microsoft.XMLHTTP"); PHPChina 开源社区门户7`Au;l n`z e
} catch (E) { PHPChina 开源社区门户'S$W5_)yo'JU
ajax = false; PHPChina 开源社区门户/Sr0m vR4f
} PHPChina 开源社区门户-xM*T1M"xL}fbHE
}PHPChina 开源社区门户|TzV3T/N:~
if (!ajax && typeof XMLHttpRequest!='undefined') {
g-kX@0@D z8k0 ajax = new XMLHttpRequest();
)DOY \~s*WH0 } PHPChina 开源社区门户;g Ho9y P#[
return ajax;
c^4?If w0}
你也许会说,这个代码因为要调用XMLHTTP组件,是不是只有IE浏览器能使,不是的经我试验,Firefox也是能使用的。PHPChina 开源社区门户m6a1R*HG%b
那么我们在执行任何Ajax操作之前,都必须先调用我们的InitAjax()函数来实例化一个Ajax对象。
PHPChina 开源社区门户t.sCx)P9MTuQ
2. 使用Get方式
现在我们第一步来执行一个Get请求,加入我们需要获取 /show.php?id=1的数据,那么我们应该怎么做呢?PHPChina 开源社区门户6f(n w.h`Fm ] S
假设有一个链接:<a href="/show.php?id=1">新闻1</a>,我点该链接的时候,不想任何刷新就能够看到链接的内容,那么我们该怎么做呢?
//将链接改为:
X4Uhv2B;q#_;R}&v0<a href="#" ōnClick="getNews(1)">新闻1</a>
//并且设置一个接收新闻的层,并且设置为不显示:PHPChina 开源社区门户N E-k:H'p
<div id="show_news"></div>
同时构造相应的Javascrīpt函数:
function getNews(newsID)PHPChina 开源社区门户}l NG@v.p?/e9ANK\
{PHPChina 开源社区门户v g+ij%YX2c)i&h
//如果没有把参数newsID传进来PHPChina 开源社区门户,K'oky8rh r4vw
if (typeof(newsID) == 'undefined')PHPChina 开源社区门户*d#Emn8zw*wx
{
m2]_$WH|x0 return false;
gM&^4Wdf0 }PHPChina 开源社区门户O~ WB/I
//需要进行Ajax的URL地址PHPChina 开源社区门户N0ba]&{1tL
var url = "/show.php?id="+ newsID;
//获取新闻显示层的位置
l2H^6^v/P]&Q|2d8q4}0 var show = document.getElementById("show_news");
//实例化Ajax对象PHPChina 开源社区门户 V1kJZ4Tc1c4y
var ajax = InitAjax();
//使用Get方式进行请求PHPChina 开源社区门户,d%Dr8\+{ X
ajax.open("GET", url, true);
//获取执行状态
I4L1kS5](@0 ajax.onreadystatechange = function() { PHPChina 开源社区门户/sCfkrSz
//如果执行是状态正常,那么就把返回的内容赋值给上面指定的层PHPChina 开源社区门户7[:M&CiIF
if (ajax.readyState == 4 && ajax.status == 200) { PHPChina 开源社区门户+y8d%C#K4m W1lu
show.innerHTML = ajax.responseText; PHPChina 开源社区门户2}H0[8O!lX
} PHPChina 开源社区门户 q%uJ$K;u:q:\
}
7u+J.}+tO6H/C#n"S)Y0 //发送空PHPChina 开源社区门户`6b^y7E.p1HV
ajax.send(null);
4A4L E Kez0}
那么当,当用户点击“新闻1”这个链接的时候,在下面对应的层将显示获取的内容,而且页面没有任何刷新。当然,我们上面省略了show.php这个文件,我们只是假设show.php文件存在,并且能够正常工作的从数据库中把id为1的新闻提取出来。
这种方式适应于页面中任何元素,包括表单等等,其实在应用中,对表单的操作是比较多的,针对表单,更多使用的是POST方式,这个下面将讲述。
PHPChina 开源社区门户"YJ\~]%FH8|x
3. 使用POST方式
其实POST方式跟Get方式是比较类似的,只是在执行Ajax的时候稍有不同,我们简单讲述一下。
@H_(Z#e$MT0假设有一个用户输入资料的表单,我们在无刷新的情况下把用户资料保存到数据库中,同时给用户一个成功的提示。
//构建一个表单,表单中不需要action、method之类的属性,全部由ajax来搞定了。PHPChina 开源社区门户!lI v4uw6v bn/} E
<form. name="user_info">
dx4[b!xE0 姓名:<input type="text" name="user_name" /><br />PHPChina 开源社区门户Q}m8[;B*y
年龄:<input type="text" name="user_age" /><br />PHPChina 开源社区门户5x9G5P+o CD9Z7R
性别:<input type="text" name="user_sex" /><br />
<input type="button" value="提交表单" ōnClick="saveUserInfo()">PHPChina 开源社区门户$L} ^ q;q3kl@V+x
</form>
;KUS4@ z Gz q(e)c M/i0//构建一个接受返回信息的层:
^)qY L&Q;L$R2@:@0<div id="msg"></div>
我们看到上面的form表单里没有需要提交目标等信息,并且提交按钮的类型也只是button,那么所有操作都是靠onClick事件中的saveUserInfo()函数来执行了。我们描述一下这个函数:
function saveUserInfo()PHPChina 开源社区门户:@{z Ir0N2} UA0j
{
j.g NU^-hTD'}0 //获取接受返回信息层
4Bl$_#Mq u7a#AI0 var msg = document.getElementById("msg");
//获取表单对象和用户信息值PHPChina 开源社区门户UkFoh1~ n
var f = document.user_info;PHPChina 开源社区门户? B5r c6[bZqh
var userName = f.user_name.value;PHPChina 开源社区门户A9e,_8wx8];c
var userAge = f.user_age.value;
\)z Pz {4w0 var userSex = f.user_sex.value;
//接收表单的URL地址
5S$C2I `xU0 var url = "/save_info.php";
//需要POST的值,把每个变量都通过&来联接PHPChina 开源社区门户(n2p4d-W gm%m/Lz2Z'n
var postStr = "user_name="+ userName +"&user_age="+ userAge +"&user_sex="+ userSex;
//实例化Ajax
K6y;IWq[[0 var ajax = InitAjax();
//通过Post方式打开连接
T;P5E"qC)b0 ajax.open("POST", url, true);
//定义传输的文件HTTP头信息
1GZ7J(Y0d8rw0 ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//发送POST数据
*P{'d V h*W$e'q0 ajax.send(postStr);
//获取执行状态
cX!` Z+_8j#ha/e0 ajax.onreadystatechange = function() { PHPChina 开源社区门户*o Z0kZ~g lc"L,c.\
//如果执行状态成功,那么就把返回信息写到指定的层里PHPChina 开源社区门户6[V5t9Pyo.Lu
if (ajax.readyState == 4 && ajax.status == 200) { PHPChina 开源社区门户h+I@$[uP4iUO A;ww
msg.innerHTML = ajax.responseText; PHPChina 开源社区门户un {6@J gq9h
} PHPChina 开源社区门户n T6a$F4c7P;R:nN;M
}
lv*k!tz0}
大致使用POST方式的过程就是这样,当然,实际开发情况可能会更复杂,这就需要开发者去慢慢琢磨。
4. 异步回调(伪Ajax方式)
一般情况下,使用Get、Post方式的Ajax我们都能够解决目前问题,只是应用复杂程度,当然,在开发中我们也许会碰到无法使用Ajax的时候,但是我们又需要模拟Ajax的效果,那么就可以使用伪Ajax的方式来实现我们的需求。
伪Ajax大致原理就是说我们还是普通的表单提交,或者别的什么的,但是我们却是把提交的值目标是一个浮动框架,这样页面就不刷新了,但是呢,我们又需要看到我们的执行结果,当然可以使用Javascrīpt来模拟提示信息,但是,这不是真实的,所以我们就需要我们的执行结果来异步回调,告诉我们执行结果是怎么样的。
假设我们的需求是需要上传一张图片,并且,需要知道图片上传后的状态,比如,是否上传成功、文件格式是否正确、文件大小是否正确等等。那么我们就需要我们的目标窗口把执行结果返回来给我们的窗口,这样就能够顺利的模拟一次Ajax调用的过程。
以下代码稍微多一点, 并且涉及Smarty模板技术,如果不太了解,请阅读相关技术资料。
上传文件:upload.html
//上传表单,指定target属性为浮动框架iframe1
1M&is^9w0uL&I0<form. action="/upload.php" method="post" enctype="multipart/form-data" name="upload_img" target="iframe1">PHPChina 开源社区门户8G m*f2@ `-xd.g$J
选择要上传的图片:<input type="file" name="image"><br />PHPChina 开源社区门户1I!H~Hu,x
<input type="submit" value="上传图片">PHPChina 开源社区门户 m4i T2cc jW?~
</form>PHPChina 开源社区门户 D?+^Z;b!ctJ8F
//显示提示信息的层PHPChina 开源社区门户`sR:z!^e7Z^`
<div id="message" style="display:none"></div>
//用来做目标窗口的浮动框架
[ l*jfX9g0<iframe. name="iframe1" width="0" height="0" scrolling="no"></iframe>
PHPChina 开源社区门户9qJ/E|6s3S3M3f_
处理上传的PHP文件:upload.php
<?php
/* 定义常量 */
//定义允许上传的MIME格式PHPChina 开源社区门户X+J7h RlV"L P c
define("UPLOAD_IMAGE_MIME", "image/pjpeg,image/jpg,image/jpeg,image/gif,image/x-png,image/png");
(rv Enja.N f1zK~0//图片允许大小,字节PHPChina 开源社区门户 oh4`v4J6dWj s"p-N
define("UPLOAD_IMAGE_SIZE", 102400);PHPChina 开源社区门户 T I}7Y4~v
//图片大小用KB为单位来表示PHPChina 开源社区门户6ElK2mM"dB/r9FQ
define("UPLOAD_IMAGE_SIZE_KB", 100); PHPChina 开源社区门户Zpq v3B Q;md?%\)Y
//图片上传的路径PHPChina 开源社区门户k#cn2o$~9O,L@ ^
define("UPLOAD_IMAGE_PATH", "./upload/");
//获取允许的图像格式PHPChina 开源社区门户-}TvH|-O L
$mime = explode(",", USER_FACE_MIME);PHPChina 开源社区门户y+xcav[
$is_vaild = 0;
//遍历所有允许格式PHPChina 开源社区门户 u,UNmvX(Rm_
foreach ($mime as $type)
DIKw/~fD3zJ`!C$J0{PHPChina 开源社区门户\E,f]K
if ($_FILES['image']['type'] == $type)PHPChina 开源社区门户*~wZ8N.M;uD1O+Dj
{PHPChina 开源社区门户&s!}&re-gzL5h AQ!n
$is_vaild = 1;
ca0x.j%L C0 }PHPChina 开源社区门户3Xu2{;h~^X
}
//如果格式正确,并且没有超过大小就上传上去PHPChina 开源社区门户!j&^6qP#p-n9g6^
if ($is_vaild && $_FILES['image']['size']<=USER_FACE_SIZE && $_FILES['image']['size']>0)PHPChina 开源社区门户v(H*FS5W
{PHPChina 开源社区门户 f/~9F uK7[
if (move_uploaded_file($_FILES['image']['tmp_name'], USER_IMAGE_PATH . $_FILES['image']['name'])) PHPChina 开源社区门户r u/\F7lrA
{
7[1b:s8~YrC [k0 $upload_msg ="上传图片成功!";PHPChina 开源社区门户M|`pj
}
l:c(p;^uF[|0 else PHPChina 开源社区门户w%M J'k4[)YA O uX
{PHPChina 开源社区门户C3H6e)\;h
$upload_msg = "上传图片文件失败";PHPChina 开源社区门户{M$Id `n
}
2y7F)X XU(|0}PHPChina 开源社区门户g%hD~Q(A,| E
else
5VH4p*P!XMyz W&]0{
g FZ#ZG'`R$n0 $upload_msg = "上传图片失败,可能是文件超过". USER_FACE_SIZE_KB ."KB、或者图片文件为空、或文件格式不正确";
'Y3S"^2p#B#W8M0}
//解析模板文件PHPChina 开源社区门户)U1z W)B f7`
$smarty->assign("upload_msg", $upload_msg);PHPChina 开源社区门户2BP9e pX$lB$P}
$smarty->display("upload.tpl");
?>
模板文件:upload.tpl
{if $upload_msg != ""}
0AtRf6iG&FFa@Z0 callbackMessage("{$upload_msg}");
*uk$c:I[]%b!Znm0{/if}
//回调的Javascrīpt函数,用来在父窗口显示信息PHPChina 开源社区门户8I1cg"utp
function callbackMessage(msg)PHPChina 开源社区门户 jMc\u/|wd
{
Yyl8C3`\iIAh:x0 //把父窗口显示消息的层打开PHPChina 开源社区门户;mc-vo!?axV H:}
parent.document.getElementById("message").style.display = "block";
6e7N b&\?3`}B `p0 //把本窗口获取的消息写上去PHPChina 开源社区门户:Za`+K"S,X,xE
parent.document.getElementById("message").innerHTML = msg;
_*qrTfX0 //并且设置为3秒后自动关闭父窗口的消息显示PHPChina 开源社区门户/T6f2S5RkdSX
setTimeout("parent.document.getElementById('message').style.display = 'none'", 3000);PHPChina 开源社区门户4t0eix2K\!ZuK
}
PHPChina 开源社区门户-]$W(\$[4CV
使用异步回调的方式过程有点复杂,但是基本实现了Ajax、以及信息提示的功能,如果接受模板的信息提示比较多,那么还可以通过设置层的方式来处理,这个随机应变吧。
[ 结束语 ]
这是一种非常良好的Web开发技术,虽然出现时间比较长,但是到现在才慢慢火起来,也希望带给Web开发界一次变革,让我们朝RIA(富客户端)的开发迈进,当然,任何东西有利也有弊端,如果过多的使用Javascrīpt,那么客户端将非常臃肿,不利于用户的浏览体验,如何在做到快速的亲前提下,还能够做到好的用户体验,这就需要Web开发者共同努力了。
相关阅读:
- Ajax原理详细说明3 (sunyu, 2006-12-21)
- php ajax 上传 显示进度 (115300111, 2006-12-22)
- 做AJAX时候浏览器缓存问题解决方案 (edwardhey, 2007-3-18)
- 使用Ajax实现友情链接无页面跳转点击统计 (£翱翔白鹭, 2008-2-14)
