ในบทเรียนรู้นี้มาทำความรู้จักและใช้งาน Dropdownlist แบบ Dependent โดย dependent dropdownlist เป็น dropdownlist ที่มีความเชื่อมโยงกัน ตัวอย่างเช่น เลือกจังหวัด จะปรากฏรายการอำเภอในจังหวัดนั้น เมื่อเลือกอำเภอก็จะปรากฏตำบลในอำเภอนั้น เป็นต้น และเราจะทำการเก็บข้อมูลตัวเลือกสุดท้ายลงในฐานข้อมูล หรือนำไปประมวลผลข้อมูลต่อไป
สำหรับบทเรียนรู้นี้จะใช้ Package ทีมีชื่อว่า DepDrop ของ Kartik ในการใช้งานโดยสามารถติดตั้งผ่านโปรแกรม Composer ได้โดยใช้คำสั่ง
composer require kartik-v/yii2-widget-depdrop
สามารถดูรายละเอียดเพิ่มเติมได้ที่
https://github.com/kartik-v/yii2-widget-depdrop
http://demos.krajee.com/widget-details/depdrop
File SQL ภาค จังหวัด อำเภอ และตำบล
ก่อนอื่นก็ดาวน์โหลด file sql ภาค จังหวัด อำเภอ และตำบลไป import ลงฐานข้อมูลกันก่อนนะครับ
http://programmerthailand.com/uploads/dep_drop.sql
Generate Model
ทำการ Generate Model ด้วย Gii ครับในที่นี้จะนำไปเก็บไว้ที่ common/models ซึ่งมีรายละเอียดดังต่อไปนี้
common/models/Region.php
<?php
namespace common\models;
use Yii;
/**
* This is the model class for table "region".
*
* @property integer $id
* @property string $name
*
* @property Province[] $provinces
*/
class Region extends \yii\db\ActiveRecord
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'region';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['id', 'name'], 'required'],
[['id'], 'integer'],
[['name'], 'string', 'max' => 255],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'name' => 'ภาค',
];
}
/**
* @return \yii\db\ActiveQuery
*/
public function getProvinces()
{
return $this->hasMany(Province::className(), ['region_id' => 'id']);
}
}
common/models/Province.php
<?php
namespace common\models;
use Yii;
/**
* This is the model class for table "province".
*
* @property integer $id
* @property string $code
* @property string $name
* @property integer $region_id
*
* @property District[] $districts
* @property Region $region
*/
class Province extends \yii\db\ActiveRecord
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'province';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['id', 'code', 'name'], 'required'],
[['id', 'region_id'], 'integer'],
[['code'], 'string', 'max' => 2],
[['name'], 'string', 'max' => 150],
[['region_id'], 'exist', 'skipOnError' => true, 'targetClass' => Region::className(), 'targetAttribute' => ['region_id' => 'id']],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'code' => 'รหัสจังหวัด',
'name' => 'จังหวัด',
'region_id' => 'ภาค',
];
}
/**
* @return \yii\db\ActiveQuery
*/
public function getDistricts()
{
return $this->hasMany(District::className(), ['province_id' => 'id']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getRegion()
{
return $this->hasOne(Region::className(), ['id' => 'region_id']);
}
}
common/models/District.php
<?php
namespace common\models;
use Yii;
/**
* This is the model class for table "district".
*
* @property integer $id
* @property string $code
* @property string $name
* @property integer $province_id
*
* @property Province $province
* @property Subdistrict[] $subdistricts
*/
class District extends \yii\db\ActiveRecord
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'district';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['id', 'code', 'name'], 'required'],
[['id', 'province_id'], 'integer'],
[['code'], 'string', 'max' => 4],
[['name'], 'string', 'max' => 150],
[['province_id'], 'exist', 'skipOnError' => true, 'targetClass' => Province::className(), 'targetAttribute' => ['province_id' => 'id']],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'code' => 'รหัสอำเภอ',
'name' => 'อำเภอ',
'province_id' => 'จังหวัด',
];
}
/**
* @return \yii\db\ActiveQuery
*/
public function getProvince()
{
return $this->hasOne(Province::className(), ['id' => 'province_id']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getSubdistricts()
{
return $this->hasMany(Subdistrict::className(), ['district_id' => 'id']);
}
}
common/models/Subdistrict.php
<?php
namespace common\models;
use Yii;
/**
* This is the model class for table "subdistrict".
*
* @property integer $id
* @property string $code
* @property string $name
* @property integer $district_id
*
* @property District $district
*/
class Subdistrict extends \yii\db\ActiveRecord
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'subdistrict';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['id', 'code', 'name'], 'required'],
[['id', 'district_id'], 'integer'],
[['code'], 'string', 'max' => 6],
[['name'], 'string', 'max' => 150],
[['district_id'], 'exist', 'skipOnError' => true, 'targetClass' => District::className(), 'targetAttribute' => ['district_id' => 'id']],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'code' => 'รหัสตำบล',
'name' => 'ตำบล',
'district_id' => 'อำเภอ',
];
}
/**
* @return \yii\db\ActiveQuery
*/
public function getDistrict()
{
return $this->hasOne(District::className(), ['id' => 'district_id']);
}
}
สร้าง Model สำหรับค้นหาข้อมูล
ทำการสร้าง model สำหรับการค้นหาข้อมูล เพื่อรับข้อมูลที่เลือก ภาค จังหวัด อำเภอ และตำบล ก่อนนำข้อมูลไปใช้งานต่อไป โดยสร้างไว้ที่ common/models/MyDepDrop.php
<?php
namespace common\models;
use yii\base\Model;
class MyDepDrop extends Model
{
public $region_id;
public $province_id;
public $district_id;
public $subdistrict_id;
public function rules()
{
return [['region_id', 'province_id', 'district_id', 'subdistrict_id'], 'required'];
}
public function attributeLabels()
{
return [
'region_id' => 'ภาค',
'province_id' => 'จังหวัด',
'district_id' => 'อำเภอ',
'subdistrict_id' => 'ตำบล'
];
}
}
สร้าง Controller
ทำการสร้าง Controller เพื่อทดสอบการทำงาน หรือหากเข้าใจหลักการทำงานแล้วสามารถนำไปประยุกต์ใช้ได้เลยครับ
frontend/controllers/DepDropController.php
<?php
namespace frontend\controllers;
use common\models\District;
use common\models\MyDepDrop;
use common\models\Province;
use common\models\Subdistrict;
use Yii;
use yii\helpers\Json;
use yii\web\Controller;
class DepDropController extends Controller
{
public function actionIndex()
{
$model = new MyDepDrop();
if($model->load(Yii::$app->request->post())){
var_dump($model);
}
return $this->render('index', [
'model' => $model
]);
}
public function actionProvinceList() {
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$region_id = $parents[0];
foreach(Province::find()->where(['region_id' => $region_id])->orderBy(['name' => SORT_ASC])->all() as $province){
$out[] = ['id' => $province->id, 'name' => $province->name];
}
echo Json::encode(['output'=>$out, 'selected'=>'']);
return;
}
}
echo Json::encode(['output'=>'', 'selected'=>'']);
}
public function actionDistrictList() {
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$province_id = $parents[0];
foreach(District::find()->where(['province_id' => $province_id])->orderBy(['name' => SORT_ASC])->all() as $district){
$out[] = ['id' => $district->id, 'name' => $district->name];
}
echo Json::encode(['output'=>$out, 'selected'=>'']);
return;
}
}
echo Json::encode(['output'=>'', 'selected'=>'']);
}
public function actionSubdistrictList() {
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$subdistrict_id = $parents[0];
foreach(Subdistrict::find()->where(['district_id' => $subdistrict_id])->orderBy(['name' => SORT_ASC])->all() as $subdistrict){
$out[] = ['id' => $subdistrict->id, 'name' => $subdistrict->name];
}
echo Json::encode(['output'=>$out, 'selected'=>'']);
return;
}
}
echo Json::encode(['output'=>'', 'selected'=>'']);
}
}
สร้าง View
ทำการสร้าง view ใน frontend/views/dep-drop/index.php
<?php
use common\models\Region;
use kartik\depdrop\DepDrop;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Url;
use yii\widgets\ActiveForm;
$this->title = 'ภาค จังหวัด อำเภอ และตำบล';
?>
<h1><?=$this->title?></h1>
<?php $form = ActiveForm::begin()?>
<?=$form->field($model, 'region_id')->dropDownList(ArrayHelper::map(Region::find()->all(), 'id', 'name'), ['prompt' => 'เลือกภาค'])?>
<?=$form->field($model, 'province_id')->widget(DepDrop::className(), [
'pluginOptions' => [
'depends' => [Html::getInputId($model, 'region_id')],
'placeholder' => 'เลือกจังหวัด',
'url' => Url::to(['province-list'])
]
])?>
<?=$form->field($model, 'district_id')->widget(DepDrop::className(), [
'pluginOptions' => [
'depends' => [Html::getInputId($model, 'province_id')],
'placeholder' => 'เลือกอำเภอ',
'url' => Url::to(['district-list'])
]
])?>
<?=$form->field($model, 'subdistrict_id')->widget(DepDrop::className(), [
'pluginOptions' => [
'depends' => [Html::getInputId($model, 'district_id')],
'placeholder' => 'เลือกตำบล',
'url' => Url::to(['subdistrict-list'])
]
])?>
<?= Html::submitButton('ส่งข้อมูล', ['class' => 'btn btn-success'])?>
<?php ActiveForm::end()?>
เมื่อเลือกภาค จังหวัด อำเภอ และตำบลแล้วจะสามารถส่งข้อมูล และแสดงผลข้อมูลผ่าน var_dump($model) ดังนี้
D:\wamp64\www\yii2-survey\frontend\controllers\DepDropController.php:22:
object(common\models\MyDepDrop)[61]
public 'region_id' => string '3' (length=1)
public 'province_id' => string '23' (length=2)
public 'district_id' => string '325' (length=3)
public 'subdistrict_id' => string '2951' (length=4)
private '_errors' (yii\base\Model) => null
private '_validators' (yii\base\Model) =>
object(ArrayObject)[62]
private 'storage' =>
array (size=1)
0 =>
object(yii\validators\RequiredValidator)[65]
...
private '_scenario' (yii\base\Model) => string 'default' (length=7)
private '_events' (yii\base\Component) =>
array (size=0)
empty
private '_behaviors' (yii\base\Component) =>
array (size=0)
empty
จะเห็นว่าเราสามารถเรียกใช้งาน object ได้เรียบร้อยแล้ว โดยข้อมูลที่จะนำไปใช้คือ
public 'region_id' => string '3' (length=1)
public 'province_id' => string '23' (length=2)
public 'district_id' => string '325' (length=3)
public 'subdistrict_id' => string '2951' (length=4)
ความคิดเห็น