使用Zend Framework和jQuery实现有Ajax效果的区域选择

2009年12月2日 发表评论 阅读评论

本文内容

带Ajax效果的区域选择表单是很常见的功能,本文章描述怎么通过Zend Framework和jQuery实现带有Ajax效果的三级省市区的选择表单。在本文中,使用Zend_Controller的动作助手来方便的生成 JSON,以及如何通过jQuery处理返回的JSON。本文不对Ajax的原理进行介绍,也不对Zend_Controller的使用进行讲解,如有需 要,可查看参考资料。

创建Zend Framework项目

按照Zend Framework手册中8.1.2.1. Create your filesystem layout节创建目录结构并创建相关文件。

application/

  controllers/

    IndexController.php

  models/

  views/

    scripts/

      index/

        index.phtml

      helpers/

      filters/
html/

  .htaccess

  index.php

该结构并不是必须的,文章中的例子只是此目录说明使用方法。

添加区域信息数据库

首先,创建一个数据库,比如名为test_area。然后,导入area.sql(以提供下载)文件进数据库,比如:mysql.exe -u root test_area < area.sql。如果您不熟悉mysql命令行,可以使用phpMyAdmin这个工具。依然是先创建数据库。

dmfmkm8_56fnxj8pgf_b

导入数据库文件。

dmfmkm8_57dzhqhkdt_b

选择,sql文件,其最大限制取决于您的php.ini配制。

dmfmkm8_58d4s6d4gp_b

实现Area Model

这里实现一个类,来处理对数据库的操作,文件位于models目录下,文件名为Area.php。代码如下:

<?php  
class Area  
{  
    protected $_db = null;  
 
    const city_tablename = 'city';  
    const area_tablename = 'area';  
    const province_tablename = 'province';  
 
    public function __construct()  
    {  
        $this->_db = Zend_Registry::get('db');  
    }  
 
    public function getCityList($father = 110000)  
    {  
        $sql = 'SELECT cityID,city FROM ' . self::city_tablename;  
        if ($father !== null) {  
            $sql .= ' WHERE father = ' . $father;  
        }  
 
        $city = $this->_db->fetchPairs($sql);  
 
        if (count($city) > 0) return $city;  
 
        return array();  
    }  
 
    public function getAreaList($city = 110100)  
    {  
        $sql = 'SELECT areaID,area FROM ' . self::area_tablename;  
        if ($city !== null) {  
            $sql .= ' WHERE father = ' . $city;  
        }  
 
        $area = $this->_db->fetchPairs($sql);  
 
        if (count($area)) return $area;  
 
        return array();  
    }  
 
    public function getProvinceList()  
    {  
        $sql = 'SELECT provinceID,province FROM ' . self::province_tablename;  
 
        $province = $this->_db->fetchPairs($sql);  
 
        if (count($province)) return $province;  
 
        return array();  
    }  
 
    public function getAreaName($id)  
    {  
        $id = intval($id);  
        $sql = 'SELECT area   
                FROM ' . self::area_tablename . '  
                WHERE areaId = ?  
                LIMIT 1';  
 
        $result = $this->_db->fetchOne($sql, $id);  
 
        if (count($result) > 0) return $result;  
 
        return false;  
    }  
 
    protected function _getCity($id, $name)  
    {  
        $id = intval($id);  
        $sql = "SELECT c." . $name . "   
                FROM " . self::city_tablename . " as c    
                LEFT JOIN " . self::area_tablename . " as a   
                ON a.father = c.cityID WHERE areaID = ?";  
 
        $result = $this->_db->fetchOne($sql, $id);  
 
        if (count($result) > 0) return $result;   
 
        return false;  
    }  
 
    public function getCityName($id)  
    {  
        return $this->_getCity($id, 'city');  
    }  
 
    public function getCityId($id)  
    {  
        return $this->_getCity($id, 'cityID');  
    }  
    public function getProvince($id)  
    {  
        $id = intval($id);  
        $sql = "SELECT p.provinceID   
                FROM " . self::province_tablename . " as p    
                LEFT JOIN " . self::city_tablename . " as c   
                ON c.father = p.provinceID WHERE cityID = ?";  
 
        $result = $this->_db->fetchOne($sql, $id);  
 
        if (count($result) > 0) return $result;  
 
        return false;  
    }  
}  
创建显示页面
 
我们的index.php是这样的。
 
<?php  
set_include_path('.' .  PATH_SEPARATOR . '../application/models/' . PATH_SEPARATOR . get_include_path());  
require_once 'Zend/Controller/Front.php';  
require_once 'Zend/Registry.php';  
require_once 'Zend/Db.php';  
 
$registry = Zend_Registry::getInstance();  
 
$params = array (  
    'host' => '127.0.0.1',  
    'username' => 'root',  
    'password' => '',  
    'dbname' => 'area_test'  
);  
 
$registry['db'] = Zend_Db::factory('PDO_MYSQL', $params);  
$registry['db']->getConnection()->exec('SET NAMES utf8');  
 
$front = Zend_Controller_Front::getInstance();  
$front->throwExceptions(true);  
 
Zend_Controller_Front::run('../application/controllers');

创建显示页面

我们的index.php是这样的。

<?php  
set_include_path('.' .  PATH_SEPARATOR . '../application/models/' . PATH_SEPARATOR . get_include_path());  
require_once 'Zend/Controller/Front.php';  
require_once 'Zend/Registry.php';  
require_once 'Zend/Db.php';  
 
$registry = Zend_Registry::getInstance();  
 
$params = array (  
    'host' => '127.0.0.1',  
    'username' => 'root',  
    'password' => '',  
    'dbname' => 'area_test'  
);  
 
$registry['db'] = Zend_Db::factory('PDO_MYSQL', $params);  
$registry['db']->getConnection()->exec('SET NAMES utf8');  
 
$front = Zend_Controller_Front::getInstance();  
$front->throwExceptions(true);  
 
Zend_Controller_Front::run('../application/controllers');

创建表单的显示页面,IndexController

<?php  
require_once 'Zend/Controller/Action.php';  
require_once 'Area.php';  
 
class IndexController extends Zend_Controller_Action   
{  
    public function indexAction()   
    {  
        $area = new Area();  
        $this->view->city = $area->getCityList();  
        $this->view->area = $area->getAreaList();  
        $this->view->province = $area->getProvinceList();  
    }  
}

初始化显示,默认显示的是北京的区域信息。 模版是这样的:

<!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>Zend Framework和jQuery实现带有Ajax效果的区域选择</title>  
<script type="text/javascript" src="scripts/jquery-1.2.6.min.js"></script>  
</head>  
 
<body>  
<form id="form1" name="form1" method="post" action="">  
  <label for="province">省</label>  
 
<?= $this->formSelect('province', $this->default_province ,  
array('style'=>'width:200px;'), $this->province) ?>  
  </select>  
  <label for="city">市</label>  
  <?= $this->formSelect('city',  $this->default_city, array('style'=>'width:200px;'), $this->city) ?>  
  </select>  
  <label for="area">区</label>  
 <?= $this->formSelect('area', $this->default_area, array('style'=>'width:200px;'),  $this->area) ?>  
  </select>  
</form>  
</body>  
</html>

通过Zend_View的助手,来方便的实现表单的构造。在Zend Framework中,并没有一个模版语言的实现,因为PHP本身就是一种模版语言。如果您觉得不能满足您的要求,可以查看Zend Framework手册中Zend_View使用其它的模版系统的章节。

输出JSON

在Zend_Controller中,通过动作助手可以方便的输入JSON文件。而且动作助手是可扩展的,您可以写自己的相关动作助手。

<?php  
require_once 'Zend/Controller/Action.php';  
require_once 'Area.php';  
 
class AjaxController extends Zend_Controller_Action {  
    public $area = null;  
 
    public function indexAction() {  
 
    }  
 
    public function init() {  
        $this->area = new Area();  
    }  
 
    public function cityAction() {  
        $request = $this->getRequest();  
        if ($request->isXmlHttpRequest()) {  
            $p = intval($request->getQuery('p'));  
            $this->_helper->getHelper('Json')->sendJson($this->area->getCityList($p));  
        }  
    }  
 
    public function areaAction() {  
        $request = $this->getRequest();  
 
        if ($request->isXmlHttpRequest()) {  
            $c = intval($request->getQuery('c'));  
            $this->_helper->getHelper('Json')->sendJson($this->area->getAreaList($c));  
        }  
    }  
}  
?>

这个控制器专门用来处理ajax请求。通过Zend_Controller_Request_Http对象的isXmlHttpRequest()方法可以检测请求是否是通过Ajax。

添加jQuery代码

<script  type="text/javascript">  
function updateArea()  
{  
    var tmp_a = $('#area').attr('disabled', 'disabled');  
    $.getJSON('ajax/area', {c:$('#city').val()}, function(json){  
        var html = '';  
        $.each(json, function(k, i){  
            html += '<option value="' + k + '">' + i + '</option>';  
        });  
        $('#area').html(html);  
        tmp_a.removeAttr('disabled');  
    });  
}  
 
function provinceChange()  
{  
    var tmp_c = $('#city').attr('disabled', 'disabled');  
       $.getJSON('ajax/city', {p:$('#province').val()}, function(json){  
           var html = '';  
           $.each(json, function(k, i){  
              html += '<option value="' + k + '">' + i + '</option>';  
        });  
        $('#city').html(html);  
        tmp_c.removeAttr('disabled');  
        var first_c = $('#city option:first').val();  
        updateArea();  
    });  
}  
 
$(function(){  
    $('#province').change(function(){  
        provinceChange();  
    });  
 
    $('#city').change(function(){  
        updateArea();  
    });  
});  
</script>

jQuery.getJSON是一个专门用来通过Ajax获取JSON数据的方法。在callback中接受一个变量,这个变量是已经转换后的JSON对象。

总结

通过Zend Framework输出JSON是非常方便的,而jQuery也能很方便的处理JSON输出,而jQuery强大的功能,通过少量的代码完成许多实现的功能。通过Zend_Controller的动作助手可以完成许多特定的功能,通过将这些特定的功能封装在一个动作助手里面,可以进行更大的对代码进行复用。类似的还有Zend_View中的助手,Zend_Layout中的区域助手Partial Helper也能够大量的对代码进行复用。

下载

  1. hh
    2010年4月13日22:33 | #1

    我自己下下来试了一下,结果效果没有表达出来。求答复

  2. admin
    2010年4月15日20:40 | #2

    你应该先检查一下有可能是那方面的问题,就算我想答复你也无从开始。

  3. 2010年5月3日22:18 | #3

    呼 雖然有卡了一下
    不過還是做出來了
    感謝你

  4. 2010年5月17日21:45 | #4

    写的不错,很有帮助。。

  5. gc
    2010年5月20日18:43 | #5

    可以了,非常感谢

  1. 本文目前尚无任何 trackbacks 和 pingbacks.