我有我的ProductsForm.php:
namespace Products\Form; use Zend\Form\Form; use Zend\Db\Adapter\AdapterInterface; use Zend\Db\TableGateway\TableGateway; use Zend\Db\Sql\Select; class ProductsForm extends Form { public function __construct(AdapterInterface $dbAdapter) { $this->adapter = $dbAdapter; parent::__construct('products'); $this->add(array( 'name' => 'state', 'type' => 'select', 'attributes' => array( 'class' => 'form-control', ), 'options' => array( 'empty_option' => 'Select...', 'value_options' => $this->getStatesForSelect() ), )); $this->add(array( 'name' => 'city', 'type' => 'select', 'attributes' => array( 'class' => 'form-control', ), 'options' => array( 'empty_option' => 'Select...', 'value_options' => $this->getCitiesForSelect() ), )); } public function getStatesForSelect() { $dbAdapter = $this->adapter; $table = new TableGateway('states', $dbAdapter); $result = $table->select(function (Select $select) { $select->order('name DESC'); }); foreach ($result as $res) { $selectData[$res['id']] = $res['name']; } return $selectData; } public function getCitiesForSelect($state_id) { ??? :( select from cities where state_id = $state_id ? } }
我只想在用户选择“state”时执行getCitiesForSelect(),然后根据state.id值用数据库中的值填充它
我该怎么做?
答案 0 :(得分:4)
首先,不要将方法getStatesForSelect
和getCitiesForSelect
放在表单中。表单是控制器层的一部分,每个数据库请求都属于模型层:
http://framework.zend.com/manual/current/en/modules/zend.mvc.intro.html
第二:如果你这样做,你可以创建一个动作,它将返回一个带有请求状态的json,并通过ajax调用它。要正确加载所有内容并且外观漂亮,您还必须对表单进行一些更改:
$this->add(array(
'name' => 'state',
'type' => 'select',
'attributes' => array(
'class' => 'form-control',
'id' => 'select-state',
),
'options' => array(
'class' => 'state-option',
'empty_option' => 'Select...',
),
));
$this->add(array(
'name' => 'city',
'type' => 'select',
'attributes' => array(
'class' => 'form-control',
'id' => 'select-city',
'style' => 'display:none',
),
'options' => array(
'empty_option' => 'Select...',
),
));
我删除了从数据库中获取选项的方法,因为如上所述,这应该是模型表的工作。你可以在控制器中设置这些选项,就像NandaKumar已写的那样:
$states = $modelTable->getStatesForSelect();
$form->get('state')->setValueOptions($states);
但这只会填补各州,我们也需要一些东西来填补城市!为此,我们将定义一个ajax动作来获取这些:
public function stateCitiesAction()
{
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH'])
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
$stateId = $this->params()->fromRoute("id");
// get your cities table
// getCitiesForSelect() needs to return an array!
$cities = $citiesTable->getCitiesForSelect();
return new JsonModel($cities);
} else {
// return a 404 if this action is not called via ajax
$this->getResponse()->setStatusCode(404);
return NULL;
}
}
if语句是为了确保,此操作只能通过ajax访问。如果不是,它将返回404。
我在这个例子中假设,模型动作将返回与表单中的方法相同的数组。虽然您可以争论哪个级别应该转换数据库结果,模型本身或控制器。但是为了保持示例简单,我就这样做了。
要正确解析JsonModel,您需要在module.config.php中包含ViewJsonStrategy。否则,您会收到错误,因为Zend会尝试查找视图脚本。
'view_manager' => array(
//...
'strategies' => array(
'ViewJsonStrategy',
),
),
另外,我们也需要传递id。路由参数是最常用的方法,我们需要在路由定义中包含它。此代码不是最终解决方案,只应向您展示如何在配置中执行此操作:
'poducts' => array(
'type' => 'Segment',
'options' => array(
'route' => '/products/[:controller][/:action][/:id]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]*',
),
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
),
有关路由的详细信息,请参阅: http://framework.zend.com/manual/current/en/modules/zend.mvc.routing.html
p,我们差不多完成了!唯一剩下的就是填补城市选项的ajax电话。我是通过jQuery做到的:$(document).ready(function () {
$("#select-state").change(function () {
var stateId = $(this).val();
if(stateId !== "") {
// you might want to change this
var url = "products/index/state-cities/"+stateId;
$.getJSON( url, function( data ) {
var options = "";
$.each(data, function(id, city) {
options += "<option value='" + id + "'>" + city + "</option>";
});
$("#select-city").html(options).fadeIn();
});
}
});
});
并非我不知道您的路由,您可能需要更改网址。