PDO(PHP Data Object) 는 이기종 데이터베이스에 접근하는 공통 API를 제공하는 것을 목적으로 만들어 졌습니다. mysqli 는 객체 스타일과, 절차적 스타일의 API를 제공하는데 비해 PDO 는 객체 스타일의 API 만을 제공합니다. PDO 는 예전에 사용하던 mysql API 와는 달리 Prepared Statement 를 제공하므로 SQL Injection 방어에 사용될 수 있습니다.
Preapred Statement 는 원래 SQL 을 미리 데이터베이스에서 컴파일해 두고, 파라미터 값만 바꿔서 처리해서 쿼리의 성능을 올리는데 사용되었지만, 요즘은 SQL Injection 방어용으로 더욱 많이 예기 되어지는것 같습니다. 그만큼 요즘은 보안이 큰 이슈로 등장 하였습니다.
PDO를 사용하기 위해서는 PHP 5.1.0 이상의 버전을 사용해야 합니다.
PHP 데이터베이스 API 를 사용하다 보면 어떤 한 작업을 하는데 즉, 동일한 기능을 구현하는데 사용할 수 있는 방법이 여러가지가 있는 경우가 많습니다.
데이터베이스에 연결하는데 사용하는 정보를 제공하는 방법이라든가, 스테이트먼트에 파라미터를 제공하는 방법 등 각각 사용하는 적절한 상황이 있어서 많은 방식이 존재할거라고 생각하지만 너무 복잡하고, 매뉴얼 찾아보기도 힘들어지는 경향이 있는 것 같습니다.
물론 이건 어디까지나 개인적인 생각입니다.
1. 데이터베이스에 연결하기
<?php
$dsn = "mysql:host=localhost;port=3306;dbname=testdb;charset=utf8";
try {
$db = new PDO($dsn, "testuser", "testuser");
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "데이터베이스 연결 성공!!<br/>";
} catch(PDOException $e) {
echo $e->getMessage();
}
?>
데이터베이스에 연결하기 위해서 PDO 객체의 생성자에 DSN(Data Source Name), 아이디, 비밀번호를 인자로 입력합니다. DSN의 port 는 기본값 3306 이 경우 생략해도 됩니다. 데이터베이스 연결 객체를 생성한 후에 setAttribute 메소드를 사용해서 두 가지 속성을 지정하고 있습니다.
- PDO::ATTR_EMULATE_PREPARES: 이 속성은 Preppared Statement 를 데이터베이스가 지원 하지 않을 경우 에뮬레이션 하는 기능으로 false 를 지정해서 데이터베이스의 기능을 사용하도록 합니다.
- PDO::ATTR_ERRMODE : 이 속성은 PDO 객체가 에러를 처리하는 방식을 결정합니다.
PDO::ERRMODE_EXCEPTION 은 에러가 발행했을때 PDOException 을 throw 하도록합니다. 이 경우 try {} catch{} 를 사용하여 에러를 처리하면 됩니다. 다른 방법으로는 PDO::ERRMODE_SILENT(에러 코드만 설정), PDO::ERRMOdE_WARNING(E_WARNING 발생)이 있습니다.
2. 조회하기
<?php $dsn = "mysql:host=localhost;port=3306;dbname=testdb;charset=utf8"; try { $db = new PDO($dsn, "testuser", "testuser"); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $keyword = "%테스트%"; $no = 1; $query = "SELECT num, name FROM tb_test WHERE name LIKE ? AND num > ?"; $stmt = $db->prepare($query); $stmt->execute(array($keyword, $no)); $result = $stmt->fetchAll(PDO::FETCH_NUM); for($i = 0; $i < count($result); $i++) { printf ("%s : %s <br />", $result[$i][0], $result[$i][1]); } } catch(PDOException $e) { echo $e->getMessage(); } ?>
- 쿼리에 값을 바꿔 넣을 곳에 ? (placeholder)를 사용합니다.
- $stmt = $db->prepare($query); : 스테이트먼트를 생성합니다.
- $stmt->execute(array($keyword, $no)); : 배열로 값을 입력합니다.
- $result = $stmt->fetchAll(PDO::FETCH_NUM); : 결과를 가져옵니다.
PDO::FETCH_NUM : 숫자 인덱스 배열 반환
PDO::FETCH_ASSOC : 컬럼명이 키인 연관배열 반환
PDO::FETCH_BOTH : 위 두가지 모두
PDO::FETCH_OBJ : 컬럼명이 프로퍼티인 인명 객체 반환
파라미터가 없는 쿼리의 경우, 파라미터 배열 없이 호출하면 됩니다.
<?php
$query = "SELECT num, name FROM tb_test";
$stmt = $db->prepare($query);
$stmt->execute();
?>
Prepared Statement를 사용하는 또 다른 방법이 있습니다. statement 의 bindParam 또는 bindValue 메소드를 사용하는 방법 입니다. 두 가지 메소드를 서로 대체할 수 있습니다.
- Place Holder에 ?를 사용하고 값을 지정하는 메소드에는 숫자 인덱스를 사용해서 값을 바인딩할 수 있습니다.
<?php $keyword = "%테스트%"; $no = 1; $query = "SELECT num, name FROM tb_test WHERE name LIKE ? AND num > ?"; $stmt = $db->prepare($query); $stmt->bindParam(1, $keyword, PDO::PARAM_STR); $stmt->bindParam(2, $no, PDO::PARAM_INT); //$stmt->bindValue(1, $keyword, PDO::PARAM_STR); //$stmt->bindValue(2, $no, PDO::PARAM_INT); $stmt->execute(); ?>
- Place Holder에 이름을 지정해서 그 이름에 따라 값을 지정할 수 있습니다.
<?php $keyword = "%테스트%"; $no = 1; $query = "SELECT num, name FROM tb_test WHERE name LIKE :name AND num > :num"; $stmt = $db->prepare($query); $stmt->bindParam(':name', $keyword, PDO::PARAM_STR); $stmt->bindParam(':num', $no, PDO::PARAM_INT); //$stmt->bindValue(':name', $keyword, PDO::PARAM_STR); //$stmt->bindValue(':num', $no, PDO::PARAM_INT); $stmt->execute(); ?>
- 결과 값을 fetch 하는 다른 방법 입니다.
<?php
while ($row = $stmt->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT)) {
printf ("%s : %s <br />", $row[0], $row[1]);
}
?>
3. 입력, 수정, 삭제 및 트랜잭션 처리
<?php $dsn = "mysql:host=localhost;port=3306;dbname=testdb;charset=utf8"; try { $db = new PDO($dsn, "testuser", "testuser"); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $name = "테스트"; $query = "INSERT INTO tb_test (name) VALUES (?)"; $stmt = $db->prepare($query); try { $db->beginTransaction(); $stmt->execute(array($name)); $db->commit(); $id = $db->lastInsertId(); } catch(PDOException $e) { $db->rollback(); echo $e->getMessage(); } } catch(PDOException $e) { echo $e->getMessage(); } ?>
댓글을 달아 주세요
도움ㅇ 되었습니다 감사합니다.
도움이 되셨다는 예기가 저에게도 큰 힘이 됩니다. 방문해 주셔서 감사합니다.^^
컴퓨터 고장으로 새 컴퓨터에 기존 코드를 올리려 했는데...
지난 6년간 세상이 많이 바뀌었네요.
엄청 많은 구글링과 고생을 하다가 이 글을 보고 웃게 됩니다.
감사합니다.
링크는 제가 만든 카페예요. 이 코멘트의 내용과 전혀 상관 없는... ^^;
도움이 되었다면 좋겠네요. 방문해 주셔서 감사합니다.^^
감사합니다. PDO 자료를 찾다가 왔습니다
정리를 잘해주셔서 큰 도움이 되었습니다
공감 꾸욱 누르고 갑니다~
도움이 되셨으면 좋겠네요. 방문해 주셔서 감사합니다.^^
감사합니다.
공감 누르고 글 좀 퍼가겠습니다~
방문해 주셔서 감사합니다.
퍼가시더라도 출처 꼭 남겨 주시길 바랍니다.^^
감사합니다
방문해서 주셔서 감사합니다.^^
어째 PHP 문서는 찾아보기가 좀 불편하더라구요 ㅋㅋㅋ PDO 활용법 잘봣습니다!
네. 그래도 한글로 쉽게 설명된 글을 찾을 수 없을때는 PHP API 레퍼런스에서 함수 이름 등으로 검색하고, 같이 포함되어 있는 샘플 예제들을 참조하는 것이 최고의 방법인것 같습니다.
방문해 주셔서 감사합니다.^^
공지사항
카테고리
태그목록
링크