배열 저장
PHP를 사용하여 MySQL에서 배열을 저장하고 검색하는 방법에 대한 자습서에 오신 것을 환영합니다.
PHP에 배열이 있고 데이터베이스에 저장하고 싶습니까? MySQL은 플랫 문자열, 숫자 및 타임 스탬프 만 사용합니다. 배열이나 객체를 허용하지 않습니다.
짧은 대답은 – 우리는 MySQL에 직접 배열을 삽입 할 수 없습니다.
삽입하기 전에 먼저 JSON, implode 또는 serialize를 사용하여 배열을 문자열로 변환해야 합니다. 예를 들어, $ sql =“INSERT INTO 테이블 (ID, 데이터) VALUES (999,””json_encode ($ array)”“”)”;
그러나 우리는 어떻게 그렇게 합니까? 인코딩 된 문자열을 어떻게 검색합니까? 인코딩 된 문자열이 실제로 가장 좋은 솔루션입니까? 몇 가지 예를 살펴보고 계속 읽으십시오!
ⓘ이 튜토리얼의 시작 부분에 모든 예제 코드가 포함 된 zip 파일이 포함되어 있으므로 모든 것을 복사하여 붙여 넣을 필요가 없습니다.
소스 코드 다운로드
먼저 약속 된 예제 소스 코드에 대한 다운로드 링크가 있습니다.
소스 코드 다운로드
모든 예제 코드를 다운로드하려면 여기를 클릭하십시오. MIT 라이센스에 따라 릴리스 했으므로 코드 위에 빌드하거나 자신의 프로젝트에서 자유롭게 사용할 수 있습니다.
폴더
다음은 zip 파일에서 폴더를 구성하는 방법에 대한 간략한 소개입니다.
빠른 시작
DUMMY 데이터베이스 테이블
코드로 들어가기 전에이 예제의 기초를 설정하여 시작하겠습니다. 좋아하는 색상을 저장하는 간단한 사람 테이블을 만들 것입니다.
DUMMY PEOPLE 테이블
CREATE TABLE `people` ( `id` int(11) NOT NULL, `name` varchar(255) NOT NULL, `fav_color` text NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `people` ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `name` (`name`); ALTER TABLE `people` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
Field | Description |
id | Person ID, primary key and auto-increment. |
name | The person’s name, unique. |
fav_color | The person’s favorite colors. |
데이터베이스 라이브러리
더미 예제 테이블을 만들었으므로 이제 모든 SQL 무거운 작업을 수행 할 각각의 PHP 라이브러리 파일을 작성하겠습니다.
데이터베이스 라이브러리
/* [SETTINGS] */ // 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', ''); /* [DATABASE LIBRARY] */ class DB { private $pdo = null; private $stmt = null; 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 ] ); } // ERROR - CRITICAL STOP - THROW ERROR MESSAGE 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 exec ($sql, $data=null) { // exec() : run insert, replace, update, delete query // PARAM $sql : SQL query // $data : array of data try { $this->stmt = $this->pdo->prepare($sql); $this->stmt->execute($data); $this->lastID = $this->pdo->lastInsertId(); } catch (Exception $ex) { $this->error = $ex; return false; } $this->stmt = null; return true; } 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 ; } } $libDB = new DB();
Function | Description |
__construct | Constructor, automatically connects to the database when the object is created. |
__destruct | Destructor, automatically closes database connection when the object is destroyed. |
exec | Run insert, replace, update, or delete query. |
fetchAll | Run a select query, returns a multidimensional array with results from multiple rows. |
저장 및 검색 배열
이제 모든 기초가 설정되었으므로 마지막 단계는 데이터베이스 라이브러리를 사용하여 인코딩 된 문자열을 저장하는 것입니다. 그런 다음 배열을 디코딩하여 다시 검색 할 수 있습니다.
1. JSON 사용
// (1) LOAD DATABASE LIBRARY require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "2-database.php" ; // (2) LET'S CREATE A DUMMY JOHN DOE ENTRY $name = "John Doe"; $colors = ["red", "green", "blue"]; // (3) THE SQL + DATA // Note - We simply JSON encode the favorite colors into a string echo $libDB->exec( "INSERT INTO `people` (`name`, `fav_color`) VALUES (?, ?)", [$name, json_encode($colors)] ) ? "OK" : $libDB->error;
// (1) LOAD DATABASE LIBRARY require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "2-database.php" ; // (2) FETCH JOHN DOE $person = $libDB->fetchAll( "SELECT * FROM `people` WHERE `name`=?", ["John Doe"] ); // (3) THE RETRIEVED PERSON // We can get back the favorite colors with json decode if (count($person)!=false) { echo "Retrieved data: "; print_r($person); echo "<br><br><br>Decoded favorite colors: "; $colors = json_decode($person[0]['fav_color']); print_r($colors); }
이 첫 번째 방법은 json_encode를 사용하여 배열을 문자열로 인코딩 한 다음 json_decode의 반대쪽을 사용하여 다시 검색합니다. JSON이 무엇인지 모르는 분들을 위해 아래의 엑스트라 섹션에 추가 링크를 남겨 두겠습니다.
2. IMPLODE & EXPLODE
// (1) LOAD DATABASE LIBRARY require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "2-database.php" ; // (2) CREATE A DUMMY JANE DOE ENTRY $name = "Jane Doe"; $colors = ["red", "pink", "purple"]; // (3) THE SQL + DATA // Implode will "combine" the array into a string, values separated by a comma echo $libDB->exec( "INSERT INTO `people` (`name`, `fav_color`) VALUES (?, ?)", [$name, implode(",", $colors)] ) ? "OK" : $libDB->error;
// (1) LOAD DATABASE LIBRARY require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "2-database.php" ; // (2) FETCH JANE DOE FROM THE DATABSE $person = $libDB->fetchAll( "SELECT * FROM `people` WHERE `name`=?", ["Jane Doe"] ); // (3) THE RETRIEVED DATA // Explode will "seperate" the string back to an array if (count($person)!=false) { echo "Retrieved data: "; print_r($person); echo "<br><br><br>Decoded favorite colors: "; $colors = explode(",", $person[0]['fav_color']); print_r($colors); }
이것은 JSON 인 코드 / 디코딩을 사용하는 대안이며, implode를 사용하여 배열을 문자열로 결합하고 explode를 사용하여 검색하는 것입니다. 그러나 2 차원 배열 (인덱싱 또는 연관 배열)에서만 작동합니다.
3. SERIALIZE & UNSERIALIZE
// (1) LOAD DATABASE LIBRARY require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "2-database.php" ; // (2) CREATE A DUMMY JOSH DOE ENTRY $name = "Josh Doe"; $colors = ["green", "lime", "cyan"]; // (3) THE SQL + DATA // Serialize will create a string representation of a php variable, array, or object echo $libDB->exec( "INSERT INTO `people` (`name`, `fav_color`) VALUES (?, ?)", [$name, serialize($colors)] ) ? "OK" : $libDB->error;
// (1) LOAD DATABASE LIBRARY require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "2-database.php" ; // (2) FETCH JOSH DOE.COM FROM THE DATABSE $person = $libDB->fetchAll( "SELECT * FROM `people` WHERE `name`=?", ["Josh Doe"] ); // (3) THE RETRIEVED DATA // We can get back the favorite colors with unserialize if (count($person)!=false) { echo "Retrieved data: "; print_r($person); echo "<br><br><br>Decoded favorite colors: "; $colors = unserialize($person[0]['fav_color']); print_r($colors); }
이 마지막 대안은 변수, 배열 및 객체를 문자열로 인코딩하는 PHP의 방법인 직렬화 및 직렬화 해제를 사용합니다.
최고는 무엇입니까?
개인적으로 JSON은 보편적으로 지원되므로 사용하는 것이 좋습니다. PHP뿐만 아니라 Javascript, ASP, C #, Python 등도 있습니다. JSON 형식을 사용하면 플랫폼 간 현명한 작업이 훨씬 쉬워집니다.
별도 테이블 사용
인코딩 된 문자열을 사용하면 멋지지만 몇 가지 단점이 있습니다. 선호하는 색상을 독점적으로 저장할 다른 테이블을 만들어 이 섹션의 대체 솔루션을 살펴 보겠습니다.
인코딩 된 문자열이 나쁜 이유
인코딩 된 문자열에 대해 나쁜 점은 무엇입니까? 가장 인기 있는 색상을 찾아야 하는 다음 시나리오를 고려하십시오. 데이터베이스에서 인코딩 된 모든 문자열을 추출하고 디코딩 한 다음 수동으로 계산해야 합니다.
// (1) LOAD DATABASE LIBRARY require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "2-database.php" ; // (2) GET ALL COLORS + DATA CRUNCHING $all = $libDB->fetchAll("SELECT `fav_color` FROM `people`"); $total = []; foreach ($all as $a) { $colors = json_decode($a['fav_color']); foreach ($colors as $c) { if ($total[$c]) { $total[$c]++; } else { $total[$c] = 1; } } }
수천 개의 항목이 있으면 매우 느리고 비효율적입니다. 그렇기 때문에 인코딩 된 문자열이 나쁘고 스마트한 방법은 선호하는 색상을 저장하기 위해 별도의 테이블을 만드는 것입니다.
FAVORITE COLORS TABLE
CREATE TABLE `fav_color` ( `id` int(11) NOT NULL, `color` varchar(64) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `fav_color` ADD PRIMARY KEY (`id`,`color`);
Field | Description |
id | Person ID, partial primary key. |
color | Color name, partial primary key. |
STORING DATA
// (1) LOAD DATABASE LIBRARY require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "2-database.php" ; // (2) CREATE A JAY DOE ENTRY $name = "Jay Doe"; $colors = ["cyan", "magenta", "yellow", "blue"]; // Create main entry first $pass = $libDB->exec("INSERT INTO `people` (`name`) VALUES (?)", [$name]); // Create color entries if ($pass) { $id = $libDB->lastID; $sql = "INSERT INTO `fav_color` (`id`, `color`) VALUES "; $data = []; foreach ($colors as $c) { $sql .= "(?, ?),"; $data[] = $id; $data[] = $c; } $sql = substr($sql, 0, -1) . ";"; $pass = $libDB->exec($sql, $data); } // (3) DONE echo $pass ? "OK" : $libDB->error ;
이 대안 솔루션으로 데이터를 저장하는 것은 조금 더 지루할 것이지만 우리가 하는 일은 단순히 색상 배열을 반복하여 항목과 SQL을 만드는 것입니다.
RETRIEVING THE ARRAY
// (1) LOAD DATABASE LIBRARY require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "2-database.php" ; // (2) FETCH JAY DOE FROM THE DATABSE $person = $libDB->fetchAll("SELECT * FROM `people` WHERE `name`=?", ["Jay Doe"]); // (3) THE RETRIEVED DATA if ($person != false) { echo "Retrieved data: "; print_r($person); // (4) GET FAVORITE COLORS $colors = $libDB->fetchAll("SELECT `color` FROM `fav_color` WHERE `id`=?", [$person[0]['id']]); echo "<br><br><br>Favorite colors: "; print_r($colors); }
선호하는 색상을 가져 오려면 여기에서 디코딩 할 필요가 없습니다. 데이터베이스에서 모든 데이터를 다시 꺼내십시오.
별도의 테이블이 감지되는 이유
이제 선호하는 별도의 색상 표를 사용하여 단 한 줄의 SQL로 데이터 마이닝을 매우 쉽게 수행 할 수 있습니다.
// (1) LOAD DATABASE LIBRARY require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "2-database.php" ; // (2) DATA MINING // This will get colors that people like - From most popular to least popular $data = $libDB->fetchAll("SELECT `color`, COUNT(*) `count` FROM `fav_color` GROUP BY `color` ORDER BY `count` DESC"); print_r($data);
별도의 테이블을 생성하는 진정한 가치는 코딩의 편의성이 아니라 분석의 용이성에 있습니다. 따라서 몇 줄의 코드를 자르는 게으름은 적절한 데이터 마이닝을 수행하는 능력을 잃는 비용이 발생한다는 점에서 항상 장단점을 신중하게 평가하십시오.
유용한 비트 및 링크
이것으로 코드가 완성되었으며 여기에 유용한 몇 가지 추가 기능이 있습니다.
참조 및 링크
등록된 댓글이 없습니다.