계단식 종속 제거
PHP와 MySQL을 사용하여 AJAX 중심 국가, 주, 도시 드롭 다운 목록을 만드는 방법에 대한 자습서를 시작합니다. 따라서 사용자가 국가, 주 또는 도시를 선택하면 캐스케이드 로드 하는 일급 비밀 닌자 프로젝트를 진행하고 있습니까? 실제로 그렇게 어렵지는 않지만 많은 양의 데이터가 필요합니다.
이 안내서는 단계별로 수행하는 방법을 단계별로 안내합니다. 계속 읽으십시오!
ⓘ이 튜토리얼을 시작할 때 모든 예제 소스 코드가 포함 된 zip 파일을 포함 시켰으므로 모든 내용을 복사하여 붙여 넣을 필요가 없습니다.
다운로드
가장 먼저, 약속 한대로 소스 코드에 대한 다운로드 링크가 있습니다.
소스 코드 다운로드
소스 코드를 다운로드하려면 여기를 클릭하십시오. MIT 라이센스에 따라 릴리스되었으므로 그 위에 빌드하거나 자신의 프로젝트에서 자유롭게 사용하십시오.
폴더
다음은 zip 파일에서 폴더를 구성하는 방법에 대한 간략한 소개입니다.
빠른 시작
필기 해
zip 파일에는 전 세계 모든 국가와 미국의 주 및 도시에 대한 예제 데이터 만 포함되어 있습니다. 지구상의 모든 장소에 무료 데이터 소스가 없으며 zip 파일에 포함하기에는 너무 방대합니다.
데이터베이스
먼저, 기초를 마련해야 합니다 – 국가, 주 및 도시에 대한 모든 데이터를 보유 할 데이터베이스 테이블을 작성하십시오.
국가
CREATE TABLE `countries` ( `country_code` varchar(2) NOT NULL, `country_name` varchar(255) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `countries` ADD PRIMARY KEY (`country_code`), ADD KEY `country_name` (`country_name`);
Field | Description |
country_code | The ISO country code, primary key. |
country_name | The country name. |
STATES
CREATE TABLE `states` ( `country_code` varchar(2) NOT NULL, `state_code` varchar(32) NOT NULL, `state_name` varchar(255) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `states` ADD PRIMARY KEY (`country_code`,`state_code`), ADD KEY `state_name` (`state_name`);
Field | Description |
country_code | The ISO country code. Partial primary key. |
state_code | The state code or postal code. Partial primary key. |
state_name | The state name. |
CITIES
CREATE TABLE `cities` ( `country_code` varchar(2) NOT NULL, `state_code` varchar(32) NOT NULL, `city_name` varchar(255) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `cities` ADD PRIMARY KEY (`country_code`,`state_code`,`city_name`);
Field | Description |
country_name | The ISO country code. Partial primary key. |
state_code | The state code or postal code. Partial primary key. |
city_name | City name. Partial primary key. |
라이브러리 파일
계속해서 다음과 같은 토대를 마련합니다. – 데이터베이스와 함께 작동하는 데 필요한 PHP 라이브러리 파일을 만듭니다.
구성 파일
// MUTE NOTICES error_reporting(E_ALL & ~E_NOTICE); // PATH define('PATH_LIB', __DIR__ . DIRECTORY_SEPARATOR); // DATABASE SETTINGS // ! CHANGE THESE TO YOUR OWN ! define('DB_HOST', 'localhost'); define('DB_NAME', 'test'); define('DB_CHARSET', 'utf8'); define('DB_USER', 'root'); define('DB_PASSWORD', '');
구성 파일은 설명이 필요합니다 ... 데이터베이스 설정을 원하는 대로 변경하십시오.
지오 라이브러리
class Geo { /* [DATABASE HELPER FUNCTIONS] */ protected $pdo = null; protected $stmt = null; public $error = ""; public $lastID = null; function __construct() { // __construct() : connect to the database // PARAM : DB_HOST, DB_CHARSET, DB_NAME, DB_USER, DB_PASSWORD // ATTEMPT CONNECT try { $str = "mysql:host=" . DB_HOST . ";charset=" . DB_CHARSET; if (defined('DB_NAME')) { $str .= ";dbname=" . DB_NAME; } $this->pdo = new PDO( $str, DB_USER, DB_PASSWORD, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false ] ); return true; } // ERROR - DO SOMETHING HERE // THROW ERROR MESSAGE OR SOMETHING catch (Exception $ex) { print_r($ex); die(); } } function __destruct() { // __destruct() : close connection when done if ($this->stmt !== null) { $this->stmt = null; } if ($this->pdo !== null) { $this->pdo = null; } } function fetchAll ($sql, $cond=null, $key=null, $value=null) { // fetchAll() : perform select query (multiple rows expected) // PARAM $sql : SQL query // $cond : array of conditions // $key : sort in this $key=>data order, optional // $value : $key must be provided. If string provided, sort in $key=>$value order. If function provided, will be a custom sort. $result = []; try { $this->stmt = $this->pdo->prepare($sql); $this->stmt->execute($cond); // Sort in given order if (isset($key)) { if (isset($value)) { if (is_callable($value)) { while ($row = $this->stmt->fetch(PDO::FETCH_NAMED)) { $result[$row[$key]] = $value($row); } } else { while ($row = $this->stmt->fetch(PDO::FETCH_NAMED)) { $result[$row[$key]] = $row[$value]; } } } else { while ($row = $this->stmt->fetch(PDO::FETCH_NAMED)) { $result[$row[$key]] = $row; } } } // No key-value sort order else { $result = $this->stmt->fetchAll(); } } catch (Exception $ex) { $this->error = $ex; return false; } // Return result $this->stmt = null; return count($result)==0 ? false : $result ; } function fetchCol ($sql, $cond=null) { // fetchCol() : yet another version of fetch that returns a flat array // I.E. Good for one column SELECT `col` FROM `table` $this->stmt = $this->pdo->prepare($sql); $this->stmt->execute($cond); $result = $this->stmt->fetchAll(PDO::FETCH_COLUMN, 0); return count($result)==0 ? false : $result; } /* [GEO FUNCTIONS] */ function getCountries () { // getCountries() : get all countries $sql = "SELECT * FROM `countries` ORDER BY `country_name`"; return $this->fetchAll($sql, null, "country_code", "country_name"); } function getStates ($country) { // getStates() : get states of given country // PARAM $country : country code $sql = "SELECT * FROM `states` WHERE `country_code`=? ORDER BY `state_name`"; return $this->fetchAll($sql, [$country], "state_code", "state_name"); } function getCities ($country, $state) { // getCities() : get cities of given country and state // PARAM $country : country code // $state : state code $sql = "SELECT `city_name` FROM `cities` WHERE `country_code`=? AND `state_code`=? ORDER BY `city_name`"; return $this->fetchCol($sql, [$country, $state]); } }
이 도서관은 하나의 거대한 도서관이지만 침착하고 면밀히 살펴보십시오. – 2 개의 부품 만 있습니다.
Function | Description |
__construct | The constructor, automatically connects to the database when the object is created. |
__destruct | The destructor, automatically closes the database connection when the object is destroyed. |
fetchAll | Runs a select SQL query. Returns a numeric array of the results – Good for multiple row queries. |
fetchCol | Runs a specific select SQL query on a single column only. Returns a numeric array of the results. |
Function | Description |
getCountries | Get all the countries. |
getStates | Get all the states for the given country. |
getCities | Get all the cities for the given country and state. |
AJAX HANDLER
// (1) INIT require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "2a-config.php"; require PATH_LIB . "2b-lib-geo.php"; $geoLib = new Geo(); // HANDLE AJAX REQUESTS switch ($_POST['req']) { // (2) INVALID REQUEST default: echo json_encode([ "status" => 0, "message" => "Invalid request" ]); break; // (3) GET COUNTRIES case "country": $countries = $geoLib->getCountries(); echo json_encode([ "status" => $countries==false ? 0 : 1, "message" => $countries ]); break; // (4) GET STATES case "state": $states = $geoLib->getStates($_POST['country']); echo json_encode([ "status" => $states==false ? 0 : 1, "message" => $states ]); break; // (5) GET CITIES case "city": $cities = $geoLib->getCities($_POST['country'], $_POST['state']); echo json_encode([ "status" => $cities==false ? 0 : 1, "message" => $cities ]); break; }
물론 라이브러리 파일은 자체적으로 마법을 수행하지 않습니다. 따라서 이것은 AJAX 호출에 대한 데이터를 제거하는 실제 스크립트입니다. 작동 방식은 매우 간단합니다.이 핸들러에 $ _POST [ 'request']를 게시하여 원하는 것을 지정하고 필요한 매개 변수를 지정합니다.
Request | Description |
country | Get all the countries. |
state | Get states for a given country. Parameters: |
city | Get cities for a given country and state. Parameters: |
HTML
필요한 모든 기초 작업이 완료되었으므로 퍼즐의 마지막 부분은 HTML 형식으로 간단히 사용하는 것입니다.
HTML
<html> <head> <title> AJAX Country State City Dropdown Demo </title> <script src="public/3b-demo.js"></script> <link href="public/3c-demo.css" rel="stylesheet"> </head> <body> <form id="sel-form" onsubmit="return false;"> <label for="sel-country">Country</label> <select id="sel-country"></select> <label for="sel-state">State</label> <select id="sel-state"></select> <label for="sel-city">City</label> <select id="sel-city"></select> <input type="submit" value="Go"/> </form> </body> </html>
네, 여기에는 특별한 것이 없습니다. 국가, 주 및 도시 선택자가 있는 일반적인 Joe HTML 양식 일 뿐입니다.
자바 스크립트
var demo = { init : function () { // demo.init() : initialize form document.getElementById("sel-country").addEventListener("change", function(){ demo.up("state") }); document.getElementById("sel-state").addEventListener("change", function(){ demo.up("city") }); demo.up('country'); }, toggle : function (disabled) { // demo.toggle() : enable/disable form // PARAM disabled : true or false var all = document.querySelectorAll("#sel-form select, #sel-form input[type=submit]"); for (var el of all) { el.disabled = disabled; } }, up : function (target) { // demo.up() : update country, state, city via AJAX // PARAM target : target select field to load // (1) DISABLE FORM demo.toggle(true); // (2) APPEND FORM DATA var data = new FormData(); data.append('req', target); if (target=="state" || target=="city") { data.append('country', document.getElementById("sel-country").value); } if (target=="city") { data.append('state', document.getElementById("sel-state").value); } // (3) INIT AJAX var xhr = new XMLHttpRequest(); xhr.open('POST', "2c-ajax-geo.php", true); // (4) UPDATE SELECTOR ON AJAX LOAD xhr.onload = function(){ // Append options var res = JSON.parse(this.response), selector = document.getElementById("sel-" + target); selector.innerHTML = ""; if (res.status) { for (var key in res.message) { var opt = document.createElement("option"); opt.value = key; opt.innerHTML = res.message[key]; selector.appendChild(opt); } } else { var opt = document.createElement("option"); opt.innerHTML = "NA"; selector.appendChild(opt); } // Load next if (target=="country") { demo.up("state"); } if (target=="state") { demo.up("city"); } // Enable form when done loading everything if (target=="city") { demo.toggle(false); } }; // SEND xhr.send(data); } }; window.addEventListener("load", demo.init);
이것은 혼란스러운 것들 중 하나이지만, 간단하게 작동하는 방법입니다 (정확히 무슨 일이 일어나고 있는지 알고 싶다면 코드를 한 줄씩 살펴보십시오).
function | Description |
demo.init | Fires on window load.
|
demo.toggle | Helper function. Used to enable/disable the selectors so that users don’t mess with them while AJAX is still loading. |
demo.up | The main function that will do the loading. Pretty much a straightforward one that will cascade load the country, state, and city via AJAX. |
CSS
#sel-form { background: #f2f2f2; border: 1px solid #aaa; padding: 10px; max-width: 300px; } #sel-form, #sel-form input, #sel-form select { font-family: arial; font-size: 1em; } #sel-form label, #sel-form select, #sel-form input[type=submit] { box-sizing: padding-box; width: 100%; } #sel-form select { padding: 5px; margin: 10px 0; } #sel-form input[type=submit] { background: #3568ba; border: 0; padding: 10px; color: #fff; cursor: pointer; }
마지막으로 CSS에는 특별한 것이 없습니다. 물건을 더 멋지게 보이게 하는 옵션 화장품.
유용한 비트
이것이 이 프로젝트의 전부이며, 여기에 도움이 될만한 추가 정보에 대한 작은 섹션이 있습니다.
참조 및 신용
등록된 댓글이 없습니다.