데이터베이스란?
데이터의 저장, 조회, 수정을 편리하고 안전하게 할 수 있도록 고안된 소프트웨어다.
MySQL이란?
데이터베이스라는 분류의 제품군에 속한 구체적인 상품으로 ORACLE에 의해서 개발되고 있다. 오픈소스이고, 가장 많은 사용자를 가지고 있는 데이터베이스 시스템에 속한다. MySQL과 같은 분류에 속한 데이터베이스로는 ORACLE, MSSQL 등이 있다.
데이터베이스와 PHP
일반적으로 데이터를 저장해야 하는 에플리케이션을 구축하는 경우 데이터는 데이터베이스 서버에 저장한다. PHP 에플리케이션의 코드에는 데이터베이스 서버에 접속해서 데이터를 조회/수정/삭제하는 코드를 작성한다. PHP 에플리케이션이 호출되면 PHP 엔진은 PHP 에플리케이션의 코드에 따라서 데이터베이스의 클라이언트가 되어서 데이터베이스에 접속해서 여러가지 작업을 처리한다.
선행지식
본 수업은 데이터베이스에 대한 수업이 아니라 PHP를 이용해서 데이터베이스를 제어하는 방법에 대한 수업이다. 따라서 데이터베이스 자체에 대한 설명은 수업의 범위에 포함되지 않기 때문에 MySQL 수업을 참고한다.
선행작업
아래의 명령을 입력해서 데이터베이스를 생성한다. 아래의 명령은 opentutorials라는 데이터베이스를 생성한다.
CREATE DATABASE opentutorials CHARACTER SET utf8 COLLATE utf8_general_ci;
아래 명령을 입력해서 데이터베이스 opentutorials를 선택한다.
use opentutorials;
아래 명령을 입력해서 데이터베이스 opentutorials 내에 테이블 topic을 생성한다.
CREATE TABLE topic ( id int(11) NOT NULL AUTO_INCREMENT, title varchar(255) NOT NULL , description text NULL , created datetime NOT NULL , PRIMARY KEY (id) );
PDO
PDO(PHP Data Objects)란 여러가지 데이터베이스를 제어하는 방법을 표준화시킨 것이다. 데이터베이스는 다양한 종류가 있다. 그리고 종류에 따라서 서로 다른 드라이브를 사용해 왔는데 드라이브의 종류에 따라서 데이터베이스를 제어하기 위한 API가 달랐다. PDO를 사용하면 동일한 방법으로 데이터베이스를 제어할 수 있다.
PHP의 mysql client library(mysql_connect와 같은 함수)는 PHP 5.5 버전부터 지원되지 않을 예정이다. 따라서 더 이상 새로운 에플리케이션의 경우 mysql client library를 사용해서는 안된다. 하지만 사용하는 환경이 PDO나 mysqli를 지원하지 않거나 기존의 코드가 mysql client library라면 이것의 사용법을 알아야 한다. 이런 경우 데이터베이스와 PHP 수업을 참고한다.
또한 PHP에 대한 올바른 사용법을 전파하고 있는 PHP Right Way에서는 PDO를 사용할 것을 권하고 있다. 이에 대한 내용은 PHP Right Way의 데이터베이스 편을 참고한다.
예제 트러블슈팅
Fatal error: Uncaught exception 'PDOException' with message 'could not find driver' in D:\BitNami\wampstack-5.4.21-0\apache2\htdocs\database\list.php:4 Stack trace: #0 D:\BitNami\wampstack-5.4.21-0\apache2\htdocs\database\list.php(4): PDO->__construct('mysql:host=loca...', 'root', '111111') #1 {main} thrown in D:\BitNami\wampstack-5.4.21-0\apache2\htdocs\database\list.php on line 4
이를 해결하기 위해서는 PDO 익스텐션을 활성화해야 한다. Bitnami의 윈도우 버전인 경우 아래와 같이 처리한다.
php의 디렉토리가 D:\BitNami\wampstack-5.4.21-0\php일 경우 D:\BitNami\wampstack-5.4.21-0\php\php.ini 파일을 열고 아래의 코드 앞의 ;을 제거한다.
extension=php_pdo_mysql.dll
그리고 익스텐션의 dll 파일이 설치된 디렉토리의 기본경로를 변경해준다. 아래의 경로는 필자가 설치한 Bitnami를 기준으로 한 것이기 때문에 사용자마다 다를 수 있다. 자신의 환경에 맞게 수정해준다.
extension_dir = "D:\BitNami\wampstack-5.4.21-0\php\ext"
예제
아래의 파일은 전송 버튼을 눌렀을 때 process.php 파일로 데이터를 전송한다.
input.php
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> </head> <body> <form action="./process.php?mode=insert" method="POST"> <p>제목 : <input type="text" name="title"></p> <p>본문 : <textarea name="description" id="" cols="30" rows="10"></textarea></p> <p><input type="submit" /></p> </form> </body> </html>
아래의 파일은 데이터베이스를 조작하는 작업을 모아둔 PHP 에플리케이션이다. URL에 포함된 mode의 값에 따라서 다른 작업을 하도록 switch 문을 사용했다.
process.php
<?php $dbh = new PDO('mysql:host=localhost;dbname=opentutorials', 'root', '111111', array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); switch($_GET['mode']){ case 'insert': $stmt = $dbh->prepare("INSERT INTO topic (title, description, created) VALUES (:title, :description, now())"); $stmt->bindParam(':title',$title); $stmt->bindParam(':description',$description); $title = $_POST['title']; $description = $_POST['description']; $stmt->execute(); header("Location: list.php"); break; case 'delete': $stmt = $dbh->prepare('DELETE FROM topic WHERE id = :id'); $stmt->bindParam(':id', $id); $id = $_POST['id']; $stmt->execute(); header("Location: list.php"); break; case 'modify': $stmt = $dbh->prepare('UPDATE topic SET title = :title, description = :description WHERE id = :id'); $stmt->bindParam(':title', $title); $stmt->bindParam(':description', $description); $stmt->bindParam(':id', $id); $title = $_POST['title']; $description = $_POST['description']; $id = $_POST['id']; $stmt->execute(); header("Location: list.php?id={$_POST['id']}"); break; } ?>
아래의 파일은 데이터베이스에 저장된 토픽의 리스트와 선택된 토픽의 자세한 정보를 화면에 출력하는 에플리케이션이다.
list.php
<?php $dbh = new PDO('mysql:host=localhost;dbname=opentutorials', 'root', '111111'); $stmt = $dbh->prepare('SELECT * FROM topic'); $stmt->execute(); $list = $stmt->fetchAll(); if(!empty($_GET['id'])) { $stmt = $dbh->prepare('SELECT * FROM topic WHERE id = :id'); $stmt->bindParam(':id', $id, PDO::PARAM_INT); $id = $_GET['id']; $stmt->execute(); $topic = $stmt->fetch(); } ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <style type="text/css"> body { font-size: 0.8em; font-family: dotum; line-height: 1.6em; } header { border-bottom: 1px solid #ccc; padding: 20px 0; } nav { float: left; margin-right: 20px; min-height: 1000px; min-width:150px; border-right: 1px solid #ccc; } nav ul { list-style: none; padding-left: 0; padding-right: 20px; } article { float: left; } .description{ width:500px; } </style> </head> <body id="body"> <div> <nav> <ul> <?php foreach($list as $row) { echo "<li><a href=\"?id={$row['id']}\">".htmlspecialchars($row['title'])."</a></li>"; } ?> </ul> <ul> <li><a href="input.php">추가</a></li> </ul> </nav> <article> <?php if(!empty($topic)){ ?> <h2><?=htmlspecialchars($topic['title'])?></h2> <div class="description"> <?=htmlspecialchars($topic['description'])?> </div> <div> <a href="modify.php?id=<?=$topic['id']?>">수정</a> <form method="POST" action="process.php?mode=delete"> <input type="hidden" name="id" value="<?=$topic['id']?>" /> <input type="submit" value="삭제" /> </form> </div> <?php } ?> </article> </div> </body> </html>
아래 파일은 토픽의 내용을 수정하기 위해서 사용할 에플리케이션이다.
<?php $dbh = new PDO('mysql:host=localhost;dbname=opentutorials', 'root', '111111'); $stmt = $dbh->prepare('SELECT * FROM topic WHERE id = :id'); $stmt->bindParam(':id', $id, PDO::PARAM_INT); $id = $_GET['id']; $stmt->execute(); $topic = $stmt->fetch(); ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> </head> <body> <form action="./process.php?mode=modify" method="POST"> <input type="hidden" name="id" value="<?=$topic['id']?>" /> <p>제목 : <input type="text" name="title" value="<?=htmlspecialchars($topic['title'])?>"></p> <p>본문 : <textarea name="description" id="" cols="30" rows="10"><?=htmlspecialchars($topic['description'])?></textarea></p> <p><input type="submit" /></p> </form> </body> </html>