使用Zend Framework和jQuery实现有Ajax效果的区域选择
本文内容
带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这个工具。依然是先创建数据库。

导入数据库文件。

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

实现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也能够大量的对代码进行复用。
我自己下下来试了一下,结果效果没有表达出来。求答复
你应该先检查一下有可能是那方面的问题,就算我想答复你也无从开始。
呼 雖然有卡了一下
不過還是做出來了
感謝你
写的不错,很有帮助。。
可以了,非常感谢