废话不多说直接上车
- 创建地区表结构
DROP TABLE IF EXISTS `region`;
CREATE TABLE `region` (
`region_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '地区ID号',
`parent_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '地区父级ID',
`region_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '地区名称',
`region_type` tinyint(1) NOT NULL DEFAULT 2 COMMENT '地区级别',
PRIMARY KEY (`region_id`) USING BTREE,
INDEX `parent_id`(`parent_id`) USING BTREE,
INDEX `region_name`(`region_name`) USING BTREE,
INDEX `region_type`(`region_type`) USING BTREE,
INDEX `agency_id`(`agency_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 659009509 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '地区' ROW_FORMAT = Dynamic;
- 创建 Region Model 文件
/common/models/Region.php
<?php
namespace common\models;
use yii\db\ActiveRecord;
use yii\helpers\ArrayHelper;
class Region extends ActiveRecord
{
/**
* {@inheritdoc}
*/
public static function tableName()
{
return '{{%region}}';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['region_name'], 'required'],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'region_id' => '地区ID',
'parent_id' => '地区父级ID',
'region_name' => '地区名称',
'region_type' => '地区级别'
];
}
/**
* 获取
* @param int $parent_id
* @return array
*/
public static function getRegion($parent_id=1)
{
$regions = static::find()->where(['parent_id'=>$parent_id])->asArray()->all();
return ArrayHelper::map($regions, 'region_id', 'region_name');
}
}
- 创建ajax异步获取地区数据链接方法
/backend/controllers/common/AjaxController.php
,这个自行定义,只要可以调用就行
<?php
namespace backend\controllers\common;
use backend\controllers\BaseController;
use common\models\Region as RegionModel;
use Yii;
use yii\helpers\Html;
use yii\web\Response;
//ajax联动接口
class AjaxController extends BaseController
{
//免认证方法
public function allowAction()
{
return [];
}
/**
* 地区联动查询
* @return string
*/
public function actionGetRegion()
{
$parent_id = Yii::$app->request->get('parent_id', 0);
$regions = RegionModel::getRegion($parent_id);
$result = '';
foreach($regions as $key => $val){
$result .= Html::tag('option', $val, ['value' => $key]);
}
return $result;
}
}
- 创建地区三级联动挂件
/common/widgets/Region.php
<?php
namespace common\widgets;
use yii\base\InvalidParamException;
use yii\base\Widget;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
class Region extends Widget
{
public $model = null;
/**
* @var string 此属性不用处理
*/
public $attribute;
/**
* @var array 外层属性配置
*/
public $options = [];
/**
* @var array 省份配置
*/
public $province = [];
/**
* @var array 城市配置
*/
public $city = [];
/**
* @var array 县/区配置
*/
public $district = [];
/**
* @var mixed 数据源
*/
public $url;
public function init()
{
if (!$this->model) {
throw new InvalidParamException('model不能为null!');
}
if (empty($this->province) || empty($this->city)) {
throw new InvalidParamException('province和city不能为空!');
}
$cityId = Html::getInputId($this->model, $this->city['attribute']);
if (empty($this->city['options']['prompt'])) {
$this->city['options']['prompt'] = '选择城市';
}
$cityDefault = Html::renderSelectOptions('city', ['' => $this->city['options']['prompt']]);
$joinChar = strripos($this->url, '?') ? '&' : '?';
$url = $this->url . $joinChar;
if (!empty($this->district)) {
if (empty($this->district['options']['prompt'])) {
$this->district['options']['prompt'] = '选择县/区';
}
$districtId = Html::getInputId($this->model, $this->district['attribute']);
$districtDefault = Html::renderSelectOptions('district', ['' => $this->district['options']['prompt']]);
$this->city['options'] = ArrayHelper::merge($this->city['options'], [
'onchange' => "
if($(this).val() != ''){
$.get('{$url}parent_id='+$(this).val(), function(data) {
$('#{$districtId}').html('{$districtDefault}'+data);
})
}else{
$('#{$districtId}').html('{$districtDefault}');
}
"
]);
}
$provinceOnchangeHtml = "
if($(this).val()!=''){
$.get('{$url}parent_id='+$(this).val(), function(data) {
$('#{$cityId}').html('{$cityDefault}'+data);
})
}else{
$('#{$cityId}').html('{$cityDefault}');
}
";
if (!empty($districtId)) {
$provinceOnchangeHtml .= "$('#{$districtId}').html('{$districtDefault}');";
}
$this->province['options'] = ArrayHelper::merge($this->province['options'], [
'onchange' => $provinceOnchangeHtml
]);
}
public function run()
{
$output[] = Html::activeDropDownList($this->model, $this->province['attribute'], $this->province['items'],
$this->province['options']);
$output[] = Html::activeDropDownList($this->model, $this->city['attribute'], $this->city['items'],
$this->city['options']);
if (!empty($this->district)) {
$output[] = Html::activeDropDownList($this->model, $this->district['attribute'], $this->district['items'],
$this->district['options']);
}
return Html::tag('div', @implode("\n", $output), $this->options);
}
}
- 视图文件添加地区挂件
use common\models\Region as RegionModel;
use common\widgets\Region as RegionWidget;
...
...
<?=$form->field($model, 'city')->widget(RegionWidget::className(), [
'options' => ['class'=>'c-md-4'],
'model' => $model,
'url' => Url::toRoute(['/common/ajax/get-region']),
'province' => [
'attribute' => 'province',
'items' => RegionModel::getRegion(),
'options' => ['class'=>'form-control c-md-3 inline', 'prompt'=>'选择省份']
],
'city' => [
'attribute' => 'city',
'items' => RegionModel::getRegion($model['province']),
'options' => ['class'=>'form-control c-md-3 inline', 'prompt'=>'选择城市']
],
'district' => [
'attribute' => 'district',
'items' => RegionModel::getRegion($model['city']),
'options' => ['class'=>'form-control c-md-3 inline', 'prompt'=>'选择县/区']
],
]); ?>
Tip:
Url::toRoute(['/common/ajax/get-region'])
生成的链接,调用是第3步的方法'attribute' => 'province'
在$model
模型添加province
字段'attribute' => 'city'
在$model
模型添加city
字段'attribute' => 'district'
在$model
模型添加district
字段