PDO (PHP Data Objects)
1. PDO 소개
PDO (PHP Data Objects) 는 여러가지 데이터베이스를 객체지향적으로 제어하는 방법을 표준화 시킨 것이다. PHP 5.5 버전부터는 mysql client library를 지원하지 않을 예정이며, PHP는 데이터베이스 접근을 위해 PDO를 사용하기를 권장하고 있다.
php7에서는 아직 mysqli와 PDO같이 제공하고 있으나 추후 mysql이나 mysqli 관련 데이터베이스 접속 관련 함수는 php에서 제외 될 예정이니 참고하기 바랍니다 , 현재 PDO 환경에서 정상적으로 운영이 가능한 프로그램으로는 XpressEngine, WordPress, GNUBoard(영카트). Drupal 등이 있으나, 일부 기능(플러그인)은 정상 동작하지 않을 수 있으니 이또한 참고하여 이용해 보시기 바랍니다.
2. PDO 기본 사용법
객체 생성 : try catch 문에서 생성합니다.
try { // MySQL PDO 객체 생성 // mysql을 다른 DB로 변경하면 다른 DB도 사용 가능 $pdo = new PDO( "mysql:host=$host;dbname=$db" , $user , $pass ); // 에러 출력 $pdo ->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (Exception $e ) { echo $e ->getMessage(); } |
커넥션 닫기 : $pdo
= null;
에러 모드
// 에러 출력하지 않음 $pdo ->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); // Warning만 출력 $pdo ->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); // 에러 출력 $pdo ->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); |
SQL 실행
$st = $pdo ->prepare( 'INSERT INTO table (col1) VALUE (`val1`)' ); $st ->execute(); |
Placeholder : PDO는 SQL 인젝션을 방지하기 위해 prepare와 placeholder를 사용합니다.
// placeholder 없음. SQL 인젝션의 위험이 있음. $st = $pdo ->( "INSERT INTO table (col1, col2, col3) values ($val1, $val2, $val3)" ); // 이름 없는 placeholder. SQL 인젝션 방지. $st = $pdo ->( 'INSERT INTO table (col1, col2, col3) values (?, ?, ?)' ); // 값을 넘겨주고 실행 $st ->execute([ 'val1' , 'val2' , 'val2' ]); // 이름 있는 placeholder. SQL 인젝션 방지 $st = $pdo ->( "INSERT INTO table (col1, col2, col3) value (:col1, :col2, :col3)" ); // 값을 넘겨주고 실행 $st ->execute([ ':col1' => 'val1' , ':col2' => 'val2' , ':col3' => 'val3' ]); |
Fetch : Object, Class로 데이터를 가져오는 방법도 있지만
여기선 배열로 가져오는 방법만 소개하겠습니다.
// SELECT $st = $pdo ->( 'SELECT * FROM table' ); $st ->execute(); // Fetch 모드를 설정 $st ->setFetchMode(PDO::FETCH_ASSOC); // 1 row 씩 가져오기 while ( $row = $st ->fetch()) { echo $row [ 'col1' ]. '<br/>' ; echo $row [ 'col2' ]. '<br/>' ; echo $row [ 'col3' ]. '<br/>' ; } |
FetchAll : 한번에 모든 row를 가져올 수 있습니다.
$st
->setFetchMode(PDO::FETCH_ASSOC);
$fetch_all
=
$st
->fetchAll();
print_r(
$fetch_all
);
3. PDO 기본 심화
PDO 테스트를 위해 mysql에 test 테이블을 만들어 좀 더 배워보자.
CREATE TABLE test ( id INT UNSIGNED NOT NULL , name VARCHAR( 50 ), PRIMARY KEY (id)) |
– mysql 데이터 삽입과 갱신
prepare 를 통해 명령어를 준비한 뒤, 명령에 사용된 변수를 bindParam을 이용해 데이터를 연결한다. 이후 execute 실행하면 연결된 데이터의 값이 데이터베이스에 삽입된다. 이렇게 복잡하게 객체지향적으로 실행하는 이유는 php injection 해킹을 방지하기 위함이다.
<?php
try { $hostname=’localhost’;
$dbname=’mysqldb’;
$username=’username’;
$password=’password’;
$db=new PDO(‘mysql:host=localhost;dbname=testdb;charset=utf8′,’username’,’password’); $stmt=$db->prepare(“INSERT INTO test (name) VALUES (:col2)”);
// 첫번째열은 auto_increment 이므로 삽입할 필요가 없다.
$stmt->bindParam(‘:col2′,$data2);
$data2=”Kelvin”;
$stmt->execute();
$db=null;
}
catch(Exception $e) {
echo $e->getMessage();
}
?> |
다음은 데이터를 갱신하는 예제이다. col2는 문자열이지만 이전 mysql_query에서 사용되던 sql명령문과 달리 문자열을 ”로 감싸지 않아도 되고 변수를 연결해주기만 하면 되므로 injection이 불가능해진다.
<?php $hostname=’localhost’; $dbname=’mysqldb’; $username=’username’;$password=’password’; $db=new PDO(‘mysql:host=localhost;dbname=testdb;charset=utf8′,’username’,’password’); $stmt=$db->prepare(“UPDATE test SET name=:col2 WHERE id=:col1“); $stmt->bindParam(‘:col1’,$data1); $stmt->bindParam(‘:col2’,$data2); $data1=5; $data2=”Robin”; $stmt->execute(); $db=null; catch(Exception $e) { |
테이블에 접속하기 위해 PDO 객체를 생성하고 개수를 출력하고 접속을 닫는다.
<?php try { $hostname=’localhost’; $dbname=’mysqldb’; $username=’username’; $password=’password’; $db=new PDO(“mysql:host=$hostname;dbname=$dbname;charset=utf8″,$username,$password); $stmt=$db->prepare(“SELECT count(*) FROM test”); $stmt->execute(); $result=$stmt->fetchAll(PDO::FETCH_ASSOC); print_r($result); $db=null; // 접속닫기 } catch (PDOException $e) { echo $e->getMessage(); } ?> |
– fetch-style
PDO::FETCH_ASSOC – 배열 인덱스를 column name 으로
PDO::FETCH_BOTH (기본값) – 배열 인덱스를 column name과 0-indexed column number 둘다
PDO::FETCH_NUM – 배열 인덱스를 0-indexed column number 로
…등등
데이터를 조회할 때 데이터 전부를 fetchAll 하는 방법과 각각의 데이터를 fetch 루프를 돌리는 방법이 있다. 이를 비교하면 별차이 없다고도 하고…메모리와 속도에서 차이가 난다고 하기도 하고… 아무튼 fetch 루프를 돌리는 방법이 더 자주 쓰이는 걸로 보인다.
<?php try { $db=new PDO(‘mysql:host=localhost;dbname=testdb;charset=utf8′,’username’,’password’); $stmt=$db->prepare(“SELECT name FROM test”); $stmt->execute(); while($row=$stmt->fetch()) { echo $row[‘name’]; echo “<br>”; } $db=null; // 접속닫기 } catch (PDOException $e) { echo $e->getMessage(); } ?> |
– mysql query 결과를 PHP array에 집어넣기
조회한 결과를 php배열에 집어넣어야 할 때가 있다. 다음과 같이 루프를 돌리면 $new_array 배열에 내용이 저장된다.
while( $row=$stmt->fetch(PDO::FETCH_ASSOC) { $new_array[] = $row; } |
FETCH_ASSOC를 이용했으니, 아이템 키와 값이 새로운 배열에 저장되었을 것이다.
이를 사용하는 방법은 다음 예를 참조하자. id 열과 link 열을 참조한 경우이다.
foreach( $new_array as $array) {
echo $array[‘id’].”<br>”; // row[‘id’] 는 $array[‘id’]로 echo $array[‘link’].”<br>”; // row[‘link’] 는 $array[‘link’]로 } |
[…] PHP PDO의 소개와 기본 다지기 […]