DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> AJAX入門 >> AJAX詳解 >> ajax的server部分(php版)
ajax的server部分(php版)
編輯:AJAX詳解     

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

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved