分享
 
 
 

ajax的server部分(php版)

王朝php·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

Server端的任务通常是根据Client的请求,进行逻辑操作,并将结果响应返回。这个响应通常为XML格式(因此server端需要使用PHP的DOM创建XML响应)

1.PHP使用DOM创建XML响应,供client端的JS解析然后在页面中显示;(因此需要熟练PHP的DOM API)

其实,PHP生成XML的方法有两种:

使用DOM API;(方法一)

另一种是直接将XML的内容echo出去即可;(方法二)

见示例:

HTML页面(包含三个JS触发函数:onmouseover, onmouseout, onclick; 分别触发自己的函数)

<!doctype html public "-//w3c//dtd html 4.0 tRANSITIONAL//en">

<html>

<head>

<title> Server PHP Ajax </title>

<script type="text/javascript" src="js.js"></script>

</head>

<body>

<span onmouseover="PHPechoXML()" onmouseout="PHPDOMXML()">Default Words</span>

<div id="show"></div>

divide<input type="text" id="firstNumber"/>by

<input type="text" id="secondNumber"/>

<input type="button" value="Send" onclick="CSparameter()"/>

<div id="result"></div>

</body>

</html>

JS页面(分别定义三个JS触发函数:PHPechoXML, PHPDOMXML, 以及CSparameter)

其中有XMLHttpRequest对象创建函数,以及各自的Server响应处理函数

///////1. 创建XMLHttpRequest对象

var xmlHttp = createXmlHttpRequestObject();

function createXmlHttpRequestObject()

...{

var xmlHttp;

try

...{

// try to create XMLHttpRequest object

xmlHttp = new XMLHttpRequest();

}

catch(e)

...{

// assume IE6 or older

var XmlHttpVersions = new Array('MSXML2.XMLHTTP.6.0',

'MSXML2.XMLHTTP.5.0',

'MSXML2.XMLHTTP.4.0',

'MSXML2.XMLHTTP.3.0',

'MSXML2.XMLHTTP',

'Microsoft.XMLHTTP');

for (var i=0; i<XmlHttpVersions.length && !xmlHttp; i++)

...{

try

...{

// try to create XMLHttpRequest object

xmlHttp = new ActiveXObject(XmlHttpVersions[i]);

}

catch (e) ...{}

}

}

if (!xmlHttp)

alert("Error creating the XMLHttpRequest object.");

else

return xmlHttp;

}

///////2. JavaScript事件响应函数(onmouseover触发)

// read a file from the server

function PHPechoXML()

...{

// only continue if xmlHttp isn't void

if (xmlHttp)

...{

// try to connect to the server

try

...{

// initiate reading a file from the server

//向Server端的PHPechoXML.php文件发送异步请求

xmlHttp.open("GET", "PHPechoXML.php", true);

xmlHttp.onreadystatechange = handleRequestStateChange;

xmlHttp.send(null);

}

// display the error in case of failure

catch (e)

...{

alert("Can't connect to server: " + e.toString());

}

}

}

///////3. JavaScript事件响应函数(onmouseout触发)

function PHPDOMXML()

...{

// only continue if xmlHttp isn't void

if (xmlHttp)

...{

// try to connect to the server

try

...{

// initiate reading a file from the server

//向Server端的PHPDOMXML.php文件发送异步请求

xmlHttp.open("GET", "PHPDOMXML.php", true);

xmlHttp.onreadystatechange = handleRequestStateChange;

xmlHttp.send(null);

}

// display the error in case of failure

catch (e)

...{

alert("Can't connect to server: " + e.toString());

}

}

}

// handles the response received from the server,Server端状态回调函数

function handleRequestStateChange()

...{

if (xmlHttp.readyState == 4)

...{

// continue only if HTTP status is "OK"

if (xmlHttp.status == 200)

...{

try

...{

// read the message from the server

var xmlResponse = xmlHttp.responseXML;

//捕获IE和Opera潜在的错误

if(!xmlResponse||!xmlResponse.documentElement)

...{

throw("Invalid XML structure: "+xmlHttp.responseText);

}

//捕获FireFox的潜在错误

var rootNodeName=xmlResponse.documentElement.nodeName;

if(rootNodeName=="parsererror")

...{

throw("Invalid XML structure: "+xmlHttp.responseText);

}

//获取Server端响应的XML响应并解析,到网页中显示

// obtain the XML's document element

xmlRoot = xmlResponse.documentElement;

// obtain arrays with book titles and ISBNs

cityArray=xmlRoot.getElementsByTagName("city");

// generate HTML output

var html = "";

// iterate through the arrays and create an HTML structure

for (var i=0; i<cityArray.length; i++)

html += cityArray.item(i).firstChild.data + "<br/>";

// obtain a reference to the <div> element on the page

myDiv = document.getElementById("show");

// display the HTML output

myDiv.innerHTML = "Server says: <br />" + html;

}

catch(e)

...{

// display error message

alert("Error reading the response: " + e.toString());

}

}

else

...{

// display status message

alert("There was a problem retrieving the data: " +

xmlHttp.statusText);

}

}

}

///////4. JavaScript事件响应函数(onclick触发)

function CSparameter()

...{

// only continue if xmlHttp isn't void

if (xmlHttp)

...{

// try to connect to the server

try

...{

//获取form中的值

var firstNumber=document.getElementById("firstNumber").value;

var secondNumber=document.getElementById("secondNumber").value;

//设置为参数,对Server端的CSparameter.php进行异步请求

var param="firstNumber="+firstNumber+"&secondNumber="+secondNumber;

// initiate reading a file from the server

xmlHttp.open("GET", "CSparameter.php?"+param, true);

xmlHttp.onreadystatechange = handleRequestStateChangePara;

xmlHttp.send(null);

}

// display the error in case of failure

catch (e)

...{

alert("Can't connect to server: " + e.toString());

}

}

}

//Server状态改变回调函数(Server端接受Client端传来的参数经过逻辑计算之后返回XML响应,Client端对XML进行解析,返回更新到页面中)

// handles the response received from the server

function handleRequestStateChangePara()

...{

if (xmlHttp.readyState == 4)

...{

// continue only if HTTP status is "OK"

if (xmlHttp.status == 200)

...{

try

...{

// read the message from the server

var xmlResponse = xmlHttp.responseXML;

//捕获IE和Opera潜在的错误

if(!xmlResponse||!xmlResponse.documentElement)

...{

throw("Invalid XML structure: "+xmlHttp.responseText);

}

//捕获FireFox的潜在错误

var rootNodeName=xmlResponse.documentElement.nodeName;

if(rootNodeName=="parsererror")

...{

throw("Invalid XML structure: "+xmlHttp.responseText);

}

// obtain the XML's document element

xmlRoot = xmlResponse.documentElement;

cityArray=xmlRoot.getElementsByTagName("result");

// generate HTML output

var html = "";

// iterate through the arrays and create an HTML structure

for (var i=0; i<cityArray.length; i++)

html += cityArray.item(i).firstChild.data + "<br/>";

// obtain a reference to the <div> element on the page

myDiv = document.getElementById("result");

// display the HTML output

myDiv.innerHTML = "Server says: <br />" + html;

}

catch(e)

...{

// display error message

alert("Error reading the response: " + e.toString());

}

}

else

...{

// display status message

alert("There was a problem retrieving the data: " +

xmlHttp.statusText);

}

}

}

Server端的PHP脚本(负责接受Client端的异步请求做出响应,并以XML格式返回到Client端)

PHPechoXML.php(PHP生成XML响应的第一种方法,echo输出XML内容)

<?php

//server端的PHP生成XML文件的第一种方法,直接echo出XML

header('Content-Type: text/xml');

// generate XML header

echo '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';

echo '<cities>';

$cityArray=array('Paris','London','NewYork','Beijing','Tokoy');

foreach ($cityArray as $city)

{

echo '<city>'.$city.'</city>';

}

echo '</cities>';

?>

PHPDOMXML.php(PHP生成XML响应的第二种方法,使用PHP的DOM API,输出XML格式的响应)

<?php

header('Content-Type: text/xml');

$cityArray=array('Shanghai','Beijing','Shanxi','Shandong');

//创建一个XML文档

$dom=new DOMDocument();

//最外层的Tag

$citiesTag=$dom->createElement('cities');

$dom->appendChild($citiesTag);

//里面的Tag可以通过循环产生

foreach ($cityArray as $city)

{

$cityTag=$dom->createElement('city');

$cityName=$dom->createTextNode($city);

$cityTag->appendChild($cityName);

$citiesTag->appendChild($cityTag);

}

//将XML结构保存为字符串并输出

$xmlString=$dom->saveXML();

echo $xmlString;

?>

2. client端的与Server端的参数传递:

client端的网页中可以有form,这样可以将参数传递到server端<GET或POST方法,变量或XML>,server端根据传递的参数,生成满足要求的XML响应;(实现了client端和server端的参数交互)

见示例:

与1中一样,参数传递的PHP端的脚本如下CSparameter.php(接受Client端form异步请求的参数,进行逻辑处理,并生成XML响应发回Client端)<?php

//自定义Server端的错误处理函数

require_once('error_handler.php');

header('Content-Type: text/xml');

//接受Client端异步请求的参数

$firstNumber=$_GET['firstNumber'];

$secondNumber=$_GET['secondNumber'];

//进行逻辑计算

$result=$firstNumber/$secondNumber;

//生成XML格式的响应向Client端返回

$dom=new DOMDocument();

$resultsTag=$dom->createElement('results');

$dom->appendChild($resultsTag);

$resultTag=$dom->createElement('result');

$resultText=$dom->createTextNode($result);

$resultTag->appendChild($resultText);

$resultsTag->appendChild($resultTag);

$xmlString=$dom->saveXML();

echo $xmlString;

?>

3. PHP端的错误异常(这里说的错误或异常都是指逻辑错误)处理:

a)PHP默认情况下,发生错误或异常的时候,不会将异常抛出(这是因为php.ini中display_errors的默认置为off,错误将被保存在Apache错误日志记录中),因此编写起来很难调试。<往往浏览器显示的错不太容易定位>

b)但如果将display_errors设置为on后,错误将显示出来,但是不友好的出错信息.

http://www.knowsky.com/

c)可以编写自己的PHP错误异常处理函数(不一定要求display_errors设置为on),将错误以明显的方式显示出来,便于调试;

通常自己编写异常处理函数如下:

显示定义的Server端错误异常抛出函数error_handler.php(PHP程序中可以方便地复用)

<?php

//set a user-defined error handler function用户自定义出错异常处理方法

set_error_handler('error_handler', E_ALL);

function error_handler($errNo,$errStr,$errFile,$errLine)

{

//如果输出缓存非空,将其置空

if(ob_get_length()) ob_clean();

//定义自定义输出

$error_message='ERRNO: '.$errNo.chr(10).'TEXT: '.$errStr.chr(10).'LOCATION: '.$errFile.', Line'.$errLine;

echo $error_message;

exit;

}

?>

4.server端存取数据库<使用MySQL存取数据,从而实现真正的动态>

这个已经很经典了,可以使用MySQL或MSSQL、Oracle等

a)打开数据库;b)SQL语句Query c)关闭数据库

5.server端PHP程序封装和体系结构(server端php程序引入设计模式)

a) appname.php <接受client端请求>

b) appname.class.php <将server端的逻辑、数据库操作、错误处理等封装成类,包含属性、方法、构造函数、析构函数>

c) config.php

d) error_handler.php

一个server端引入设计模式的例子:(设计Server端PHP脚本的程序架构,增强扩展性和重用性)

一个很简单的Keywords Suggest程序:(包括index.html, css/style.css, js.js以及PHP代码php/suggest.php, suggest.class.php, error_handler.php, config.php 支持数据库)

index.html(css/style.css, js.js; 注意两个JS客户端事件触发onkeyup,onclick)

onkeyup在用户输入的时候实时异步地向Server端发送请求,Server给出响应;onclick在用户点击search的时候,向Server发送请求

<!doctype html public "-//w3c//dtd html 4.0 tRANSITIONAL//en">

<html>

<head>

<title> Design Pattern PHP AJAX (keywords suggest DEMO) </title>

<link type="text/css" rel="stylesheet" href="css/style.css"/>

<script type="text/javascript" src="js.js"></script>

</head>

<body>

<noscript>

<strong>This example requires a JavaScript-enabled browser!</strong>

</noscript>

<div class="project">

<span class="title">Welcome to Design Pattern PHP AJAX (keywords suggest DEMO) </span>

<br />

<br />

<div class="news">

<br /><input type="text" id="keyword" onkeyup="keyup()" /><input type="button" id="search" onclick="search()" value="search"><br /><br />

suggest keywords:

<div id="show"></div>

</div>

</div>

</body>

</html>

css/style.css

body

{...}{

font-family: Arial;

font-size: small;

background-color: #fff;

}

.title

{...}{

font-size:x-large;

}

div.project

{...}{

background-color: #99ccff;

padding:5px;

border:#000099 1px solid;

}

div.news

{...}{

background-color:#fffbb8;

padding:2px;

border: 1px dashed;

}

#show

{...}{

color: #008000;

font-style: italic;

}js.js(JS中定义响应函数以及Client处理Server响应的回调函数)

///////////////////////////////////////////////////////////

//1.创建XMLHttpRequest对象

///////////////////////////////////////////////////////////

var xmlHttp = createXmlHttpRequestObject();

function createXmlHttpRequestObject()

...{

var xmlHttp;

try

...{

// try to create XMLHttpRequest object

xmlHttp = new XMLHttpRequest();

}

catch(e)

...{

// assume IE6 or older

var XmlHttpVersions = new Array('MSXML2.XMLHTTP.6.0',

'MSXML2.XMLHTTP.5.0',

'MSXML2.XMLHTTP.4.0',

'MSXML2.XMLHTTP.3.0',

'MSXML2.XMLHTTP',

'Microsoft.XMLHTTP');

for (var i=0; i<XmlHttpVersions.length && !xmlHttp; i++)

...{

try

...{

// try to create XMLHttpRequest object

xmlHttp = new ActiveXObject(XmlHttpVersions[i]);

}

catch (e) ...{}

}

}

if (!xmlHttp)

alert("Error creating the XMLHttpRequest object.");

else

return xmlHttp;

}

//向id为show的div显示server端响应的正确

function display(message)

...{

showDIV=document.getElementById("show");

showDIV.innerHTML=message;

}

//向id为show的div显示server端响应的错误信息

function displayError(errormessage)

...{

//显示出错信息

display("Error retrieving the new message!<br/>"+errormessage);

}

///////////////////////////////////////////////////////////

//2. event-driven函数(keyup函数)

///////////////////////////////////////////////////////////

var keyupAddress="php/suggest.php?action=keyup&keyword=";

function keyup()

...{

if(xmlHttp)

...{

//server不忙的时候发送异步请求

if(xmlHttp.readyState==0||xmlHttp.readyState==4)

...{

try

...{

var keyword=document.getElementById("keyword").value;

//发出异步请求

xmlHttp.open("GET",keyupAddress+keyword,true);

xmlHttp.onreadystatechange=handlereadystatechange;

xmlHttp.send(null);

}

catch(e)

...{

displayError(e.toString);

}

}

}

}

///////////////////////////////////////////////////////////

//3. 回调函数,server端响应状态发生变化后激发该函数

///////////////////////////////////////////////////////////

function handlereadystatechange()

...{

if(xmlHttp.readyState==4)

...{

if(xmlHttp.status==200)

...{

try

...{

//获取server端响应

var xmlResponse = xmlHttp.responseXML;

suggestArray=xmlResponse.getElementsByTagName("suggest");

var showText="";

for(var i=0;i<suggestArray.length;i++)

...{

var textNodes=suggestArray[i].getElementsByTagName("text");

var timesNodes=suggestArray[i].getElementsByTagName("times");

for(var j=0;j<textNodes.length;j++)

...{

showText+=textNodes[j].childNodes[0].nodeValue+" ("+timesNodes[j].childNodes[0].nodeValue+") <br />";

}

}

//显示响应到页面中

display(showText);

}

catch(e)

...{

displayError(e.toString());

}

}

}

}

///////////////////////////////////////////////////////////

//2. event-driven函数(search函数)

///////////////////////////////////////////////////////////

var searchAddress="php/suggest.php?action=search&keyword=";

function search()

...{

if(xmlHttp)

...{

//server不忙的时候发送异步请求

if(xmlHttp.readyState==0||xmlHttp.readyState==4)

...{

try

...{

var keyword=document.getElementById("keyword").value;

//发出异步请求

xmlHttp.open("GET",searchAddress+keyword,true);

xmlHttp.onreadystatechange=handlereadystatechange;

xmlHttp.send(null);

}

catch(e)

...{

displayError(e.toString);

}

}

}

}

最后注意:Server端PHP脚本的程序架构(suggest.php为Server端的主要处理函数,另外suggest.class.php,error_handler.php,config.php等)

suggest.php(获取Client端的参数,并调用suggest类的两个方法,生成XML格式的响应发回到Client端)

<?php

require_once('suggest.class.php');

header('Content-Type: text/xml');

//确定用户浏览器不会缓存结果

header('Expires: Wed, 23 Dec 1980 00:30:00 GMT');

header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT' );

header('Cache-Control: no-cache, must-revalidate');

header('Pragma: no-cache');

$action=$_GET['action'];

$keyword=$_GET['keyword'];

$oSuggest=new suggest();

if($action=='keyup'&&$keyword!='')

{

$suggestXML=$oSuggest->getSuggests($keyword);

}

if($action=='search'&&$keyword!='')

{

$suggestXML=$oSuggest->submitKeyword($keyword);

}

echo $suggestXML;

?>suggest.class.php类

<?php

require_once('error_handler.php');

require_once('config.php');

class suggest

{

//成员变量

private $conn;

//构造函数, 数据库链接

function __construct()

{

$this->conn=new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE);

if (mysqli_connect_errno()) {

printf("Connect failed: %s ", mysqli_connect_error());

exit();

}

}

//析构函数,断开数据库链接

function __destruct()

{

$this->conn->close();

}

//getSuggests成员函数(该函数主要响应Client端action=keyup,即用户正在输入时候的异步请求)

public function getSuggests($keyword)

{

//产生suggest(产生数据库中与所输入关键词前半部分相同的关键词)

$suggest_query='select * from keywords where keyword like ''.$keyword.'%' order by times desc limit 5';

$suggest_result=$this->conn->query($suggest_query);

$suggest_num=$suggest_result->num_rows;

$strOUT='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';

if($suggest_num==0)

{

//$strOUT=$strOUT.'<suggests><suggest><text>'.$keyword.'</text><times>0</times></suggest></suggests>';

}

else

{

$strOUT=$strOUT."<suggests>";

for($i=0;$i<$suggest_num;$i++)

{

$suggest_row = $suggest_result->fetch_row();

$strOUT=$strOUT.'<suggest><text>'.$suggest_row[1].'</text><times>'.$suggest_row[2].'</times></suggest>';

}

$strOUT=$strOUT.'</suggests>';

}

return $strOUT;

}

//submitKeyword成员函数(该函数主要响应Client端action=search,即用户点击search时候的异步请求)

public function submitKeyword($keyword)

{

$select_query='select * from keywords where keyword=''.$keyword.''';

$select_result=$this->conn->query($select_query);

$select_num=$select_result->num_rows;

//遇到新的keywords添加到数据库中,遇到已有的keywords增加次数

$strOUT='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';

//已经存在,增加次数

if($select_num!=0)

{

$select_row = $select_result->fetch_row();

$times_now=$select_row[2];

$times_now=$times_now+1;

$update_query='update keywords set times ='.$times_now.' where keyword=''.$keyword.''';

$update_result=$this->conn->query($update_query);

$strOUT=$strOUT.'<suggests><suggest><text>'.$keyword.'</text><times>'.$times_now.'</times></suggest></suggests>';

}

else

{

//不存在保存插入

$insert_query='insert into keywords(keyword, times) values (''.$keyword.'',1)';

$insert_result=$this->conn->query($insert_query);

$strOUT=$strOUT.'<suggests><suggest><text>'.$keyword.'</text><times>1</times></suggest></suggests>';

}

return $strOUT;

}

}

?>

最后两个函数,config.php保存应用程序配置信息(如 数据库配置信息)

<?php

define('DB_HOST', 'localhost');

define('DB_USER','phpajaxuser');

define('DB_PASSWORD','phpajaxuser');

define('DB_DATABASE','phpajax');

?>

error_handler.php保存自定义异常处理

<?php

//设置用户自定义错误处理函数

set_error_handler('error_handler', E_ALL);

function error_handler($errNo,$errStr,$errFile,$errLine)

{

if(ob_get_length()) ob_clean();

$error_message='ERRNO: '.$errNo.chr(10).'TEXT: '.$errStr.chr(10).'LOCATION: '.$errFile.' Line: '.$errLine;

echo $error_message;

exit;

}

?>最后还需要sql语句向数据库中添加用于保存keywords的database

CREATE TABLE `keywords` (

`id` int(10) unsigned NOT NULL auto_increment,

`keyword` varchar(32) NOT NULL default '',

`times` int(10) unsigned NOT NULL default '0',

PRIMARY KEY (`id`)

) TYPE=MyISAM AUTO_INCREMENT=1 ;

6.关于PHP的小知识,以后研究:

PHP从远程服务器读取数据的方法(有点儿类似Web Crawl):

file_get_contents;

或者CURL<Client URL Library>www.php.net/curl

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有