PDO 개요
GOLDILOCKS PDO (PDO_GOLDILOCKS) 드라이버는 PDO에서 GOLDILOCKS 데이터베이스에 접근할 수 있도록 PDO 인터페이스를 제공한다.
PDO_GOLDILOCKS는 GOLDILOCKS CLI 드라이버를 기반으로 작성되었다. GOLDILOCKS 배포 패키지는 PHP 버전에 맞는 PDO_GOLDILOCKS 소스와 PECL 패키지 메타데이터를 제공한다.
설치/구성
요구 사항
PHP와 동일한 시스템에 GOLDILOCKS의 클라이언트 패키지를 설치하고 $GOLDILOCKS_HOME 환경 변수를 설정해야 한다.
소스를 빌드하려면 C 컴파일러와 설치된 PHP 버전에 맞는 개발 패키지가 필요하다. 또한 phpize 및 php-config 명령을 사용할 수 있어야 한다. PECL 패키지를 생성하거나 설치하려면 PEAR/PECL도 설치되어 있어야 한다.
설치
PHP 버전에 맞는 소스 선택
PDO_GOLDILOCKS 소스는 $GOLDILOCKS_HOME/app_dev/pdo 디렉터리 아래에 PHP 버전별 디렉터리로 제공된다. 설치된 PHP 버전에 맞는 소스 디렉터리를 선택한다.
PHP 버전 | 소스 디렉터리 |
|---|---|
PHP 5.1 ~ 5.6 | PDO_legacy |
PHP 7.0 ~ 8.0 | PDO_php7_to_80 |
PHP 8.1 이상 | PDO_php81_and_above |
php, phpize, php-config 명령은 모두 동일한 PHP 버전에 대응하는 것을 사용해야 한다. 다음 명령으로 설치된 PHP 버전을 확인할 수 있다.
% php -v
PECL은 PHP 버전에 맞는 소스 디렉터리를 자동으로 선택하지 않는다. 따라서 PECL을 사용하는 경우에도 위 표를 참고하여 먼저 해당 PHP 버전에 맞는 소스 디렉터리를 선택해야 한다.
PECL을 이용한 설치
선택한 소스 디렉터리에서 pecl pickle 명령을 실행하여 PECL 패키지를 생성한다. 다음은 PHP 7.0 ~ 8.0 용 소스를 사용하는 예이다.
% cd $GOLDILOCKS_HOME/app_dev/pdo/PDO_php7_to_80 % pecl pickle Attempting to process the second package file Package PDO_GOLDILOCKS-26.1.0.tgz done
PDO_GOLDILOCKS 패키지 파일이 생성되면 pecl 명령을 사용하여 패키지를 설치한다.
% sudo -E pecl install ./PDO_GOLDILOCKS-26.1.0.tgz
소스 빌드를 통한 설치
PECL 패키지를 생성하지 않고 선택한 소스 디렉터리에서 직접 빌드할 수도 있다. 다음은 PHP 7.0 ~ 8.0 용 소스를 사용하는 예이다.
소스 디렉터리로 이동한다.
% cd $GOLDILOCKS_HOME/app_dev/pdo/PDO_php7_to_80
phpize 명령을 실행하여 PDO_GOLDILOCKS 확장 모듈의 빌드 환경을 생성한다.
% phpize
php-config 명령과 $GOLDILOCKS_HOME 경로를 지정하여 빌드한다.
% ./configure --with-php-config="$(command -v php-config)" --with-pdo-goldilocks="$GOLDILOCKS_HOME"
% make
빌드한 확장 모듈을 설치한다.
% sudo -E make install
PHP 설정 파일 수정
다음 명령으로 PHP 에서 사용하는 설정 파일과 추가 설정 파일 디렉터리를 확인한다.
% php --ini
확인한 설정 파일 또는 추가 설정 파일 디렉터리의 pdo_goldilocks.ini 파일에 다음 내용을 추가한다.
extension=pdo_goldilocks.so
CLI 와 웹 서버 또는 PHP-FPM 은 서로 다른 PHP 설정 파일을 사용할 수 있으므로, 각각에서 사용하는 설정 파일을 확인해야 한다.
웹 서버 또는 PHP-FPM 재시작
PDO_GOLDILOCKS를 웹 애플리케이션에서 사용하는 경우 웹 서버 또는 PHP-FPM을 재시작한다.
PDO_GOLDILOCKS 설치 확인
다음 명령으로 PDO_GOLDILOCKS 확장 모듈과 PDO 드라이버가 활성화되었는지 확인한다.
% php -m | grep -i '^pdo_goldilocks$' pdo_goldilocks
% php -i | grep 'PDO Driver for GOLDILOCKS' PDO Driver for GOLDILOCKS => enabled
사용
데이터 원본 이름 (DSN)
PDO_GOLDILOCKS의 데이터 원본 이름 (DSN)은 다음과 같이 구성된다.
속성 | 설명 |
|---|---|
DSN prefix | goldilocks |
DSN | ODBC 데이터 원본 이름 (DSN) |
HOST | 서버의 IP 주소 |
PORT | 서버의 PORT 번호 |
UID | 사용자 ID |
PWD | 사용자 password |
사용 예
Connecting to GOLDILOCKS
print "\n[Connecting to GOLDILOCKS]\n";
$db = new PDO('goldilocks:HOST=192.168.0.16;PORT=22581', 'test', 'test');
//$db = new PDO('goldilocks:DSN=GOLDILOCKS;UID=test;PWD=test');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);Set test data
$result = $db->exec('DROP TABLE IF EXISTS t1');
$result = $db->exec('CREATE TABLE t1 ( id INTEGER GENERATED BY DEFAULT AS IDENTITY, name VARCHAR(32) )');
$result = $db->exec("INSERT INTO t1(name) VALUES ('Carol')");
$result = $db->exec("INSERT INTO t1(name) VALUES ('Ted')");
$result = $db->exec("INSERT INTO t1(name) VALUES (null)");
$result = $db->exec("INSERT INTO t1(name) VALUES ('William')");
$result = $db->exec("INSERT INTO t1(name) VALUES ('Chelsea')");
$result = $db->exec("INSERT INTO t1(name) VALUES ('Colin')");
$result = $db->exec('DROP TABLE IF EXISTS t2');
$result = $db->exec('CREATE TABLE t2 ( id INTEGER, name VARCHAR(32) )');
$result = $db->exec("INSERT INTO t2 VALUES (1, 'John')");
$result = $db->exec("INSERT INTO t2 VALUES (1, 'John')");
$result = $db->exec("INSERT INTO t2 VALUES (1, 'John')");
$result = $db->exec("INSERT INTO t2 VALUES (2, 'Smith')");
$result = $db->exec("INSERT INTO t2 VALUES (2, 'Smith')");
$result = $db->exec('DROP TABLE IF EXISTS images');
$result = $db->exec('CREATE TABLE images ( id INTEGER, contenttype VARCHAR(256), imagedata LONG VARBINARY )');
$result = $db->exec('DROP PROCEDURE IF EXISTS sp_out_string');
$result = $db->exec("CREATE OR REPLACE PROCEDURE sp_out_string( v1 OUT VARCHAR(32) ) ".
"IS ".
"BEGIN ".
" v1 := 'WORLD'; ".
"END; ");
$result = $db->exec('DROP PROCEDURE IF EXISTS sp_inout_string');
$result = $db->exec("CREATE OR REPLACE PROCEDURE sp_inout_string( v1 INOUT VARCHAR(32) ) ".
"IS ".
"BEGIN ".
" v1 := V1 || ' WORLD'; ".
"END; ");Quoting a normal string
print "\n[Quoting a normal string]\n"; $string = 'Nice'; print "Unquoted string: $string\n"; print "Quoted string : " . $db->quote($string) . "\n";
Quoting a dangerous string
print "\n[Quoting a dangerous string]\n"; $string = 'Naughty \' string'; print "Unquoted string: $string\n"; print "Quoted string :" . $db->quote($string) . "\n";
Quoting a complex string
print "\n[Quoting a complex string]\n"; $string = "Co'mpl''ex \"st'\"ring"; print "Unquoted string: $string\n"; print "Quoted string : " . $db->quote($string) . "\n";
Handling an error
print "\n[Error Handling]\n";
try
{
//connect as appropriate as above
$db->query('invalid query'); //invalid query!
}
catch(PDOException $ex)
{
print "ERROR:".$ex->getMessage()."\n";
}Retrieving column metadata
print "\n[Retrieving column metadata]\n";
$stmt = $db->query('SELECT * FROM t1');
foreach(range(0, $stmt->columnCount() - 1) as $column_index)
{
$meta = $stmt->getColumnMeta($column_index);
var_dump($meta);
}Running simple select statements
print "\n[Running Simple Select Statements]\n";
print "\n#1\n";
foreach($db->query('SELECT * FROM t1') as $row)
{
print $row['ID'].' '.$row['NAME']."\n";
}
print "\n#2\n";
$stmt = $db->query('SELECT * FROM t1');
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
print $row['ID'].' '.$row['NAME']."\n";
}Fetching rows using different fetch styles
print "\n[Fetching rows using different fetch styles]\n";
$stmt = $db->prepare("SELECT id, name FROM t1");
$stmt->execute();
print("PDO::FETCH_ASSOC: ");
print("Return next row as an array indexed by column name\n");
$result = $stmt->fetch(PDO::FETCH_ASSOC);
print_r($result);
print("\n");
print("PDO::FETCH_BOTH: ");
print("Return next row as an array indexed by both column name and number\n");
$result = $stmt->fetch(PDO::FETCH_BOTH);
print_r($result);
print("\n");
print("PDO::FETCH_LAZY: ");
print("Return next row as an anonymous object with column names as properties\n");
$result = $stmt->fetch(PDO::FETCH_LAZY);
print_r($result);
print("\n");
print("PDO::FETCH_OBJ: ");
print("Return next row as an anonymous object with column names as properties\n");
$result = $stmt->fetch(PDO::FETCH_OBJ);
print $result->NAME;
print("\n");Fetching rows with a scrollable cursor
print "\n[Fetching rows using different fetch styles]\n";
print "\n[Fetching rows with a scrollable cursor]\n";
$sql = 'SELECT id, name FROM t1 ORDER BY id';
print "Reading forwards:\n";
try
{
$stmt = $db->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$stmt->execute();
while( $row = $stmt->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT) )
{
$data = $row[0] . "\t" . $row[1] . "\n";
print $data;
}
$stmt = null;
}
catch (PDOException $e)
{
print $e->getMessage();
}
print "Reading backwards:\n";
try
{
$stmt = $db->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_LAST);
do
{
$data = $row[0] . "\t" . $row[1] . "\n";
print $data;
} while( $row = $stmt->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_PRIOR) );
$stmt = null;
}
catch (PDOException $e)
{
print $e->getMessage();
}Constructing an order
print "\n[Construction order]\n";
class Person
{
private $NAME;
public function __construct()
{
$this->tell();
}
public function tell()
{
if (isset($this->NAME))
{
print "I am {$this->NAME}.\n";
}
else
{
print "I don't have a name yet.\n";
}
}
}
$stmt = $db->query("SELECT name FROM t1");
$stmt->setFetchMode(PDO::FETCH_CLASS, 'Person');
$person = $stmt->fetch();
$person->tell();
$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'Person');
$person = $stmt->fetch();
$person->tell();Running simple INSERT, UPDATE, or DELETE statements
print "\n[Running Simple INSERT, UPDATE, or DELETE statements]\n";
$affected_rows = $db->exec("INSERT INTO t1(name) VALUES ('John'), ('Marry')");
print $affected_rows." were affected\n";Getting the last insert id
print "\n[Getting the Last Insert Id]\n";
$affected_rows = $db->exec("INSERT INTO t1(name) VALUES ('Smith')");
$insertId = $db->lastInsertId();
print "last insert id : ".$insertId."\n";Running statements with parameters
print "\n[Running Statements With Parameters]\n";
print "\n#1 array\n";
$id = 1;
$name = 'John';
$stmt = $db->prepare("SELECT * FROM t2 WHERE id=? AND name=?");
$stmt->execute(array($id, $name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
var_dump($rows);
print "\n#2 bindValue\n";
$id = 2;
$name = 'Smith';
$stmt = $db->prepare("SELECT * FROM t2 WHERE id=? AND name=?");
$stmt->bindValue(1, $id, PDO::PARAM_INT);
$stmt->bindValue(2, $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
var_dump($rows);Named placeholders
print "\n[Named Placeholders]\n";
print "\n#1 array\n";
$id = 1;
$name = 'John';
$stmt = $db->prepare("SELECT * FROM t2 WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
var_dump($rows);
print "\n#2 bindValue\n";
$id = 2;
$name = 'Smith';
$stmt = $db->prepare("SELECT * FROM t2 WHERE id=:id AND name=:name");
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
var_dump($rows);Executing prepared statements in a loop
print "\n[Executing prepared statements in a loop]\n";
$values = array('bob', 'alice', 'lisa', 'john');
$name = '';
$stmt = $db->prepare("INSERT INTO t1(name) VALUES(:name)");
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
foreach($values as $name)
{
$stmt->execute();
}
foreach($db->query('SELECT * FROM t1') as $row)
{
print $row[0].' '.$row[1]."\n";
}Calling a stored procedure with an output parameter
print "\n[Calling a stored procedure with an output parameter]\n";
$stmt = $db->prepare("CALL sp_out_string(?)");
$stmt->bindParam(1, $value, PDO::PARAM_STR, 32);
$stmt->execute();
print "procedure returned $value\n";Calling a stored procedure with an input/output parameter
print "\n[Calling a stored procedure with an input/output parameter]\n";
$stmt = $db->prepare("CALL sp_inout_string(?)");
$value = 'HELLO';
$stmt->bindParam(1, $value, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 32);
$stmt->execute();
print "procedure returned $value\n";Transactions
print "\n[Transactions]\n";
print "\n#1 commit\n";
try
{
$db->beginTransaction();
$db->exec("INSERT INTO t1(name) VALUES('kim')");
$name = 'lee';
$stmt = $db->prepare("INSERT INTO t1(name) VALUES(?)");
$stmt->execute(array($name));
$id = 3;
$name = 'park';
$stmt = $db->prepare("INSERT INTO t2 VALUES(?, ?)");
$stmt->execute(array($id, $name));
$db->commit();
}
catch(PDOException $ex)
{
//Something went wrong rollback!
$db->rollBack();
print $ex->getMessage()."\n";
}
print "\nT1\n";
foreach($db->query('SELECT * FROM t1') as $row)
{
print $row[0].' '.$row[1]."\n";
}
print "\nT2\n";
foreach($db->query('SELECT * FROM t2') as $row)
{
print $row[0].' '.$row[1]."\n";
}
print "\n#2 rollback\n";
try
{
$db->beginTransaction();
$db->exec("INSERT INTO t1(name) VALUES('KIM')");
$name = 'LEE';
$stmt = $db->prepare("INSERT INTO t1(name) VALUES(?)");
$stmt->execute(array($name));
$id = 3;
$name = 'PARK';
$stmt = $db->prepare("INSERT INTO invalid VALUES(?, ?)");
$stmt->execute(array($id, $name));
$db->commit();
}
catch(PDOException $ex)
{
//Something went wrong rollback!
$db->rollBack();
print $ex->getMessage()."\n";
}
print "\nT1\n";
foreach($db->query('SELECT * FROM t1') as $row)
{
print $row[0].' '.$row[1]."\n";
}
print "\nT2\n";
foreach($db->query('SELECT * FROM t2') as $row)
{
print $row[0].' '.$row[1]."\n";
}Inserting an image into a database
print "\n[Inserting an image into a database]\n";
try
{
$stmt = $db->prepare("INSERT INTO images (id, contenttype, imagedata) VALUES (?, ?, ?)");
$id = 1;
$type = "image/png";
$fp = fopen("logo.png", "rb");
$stmt->bindParam(1, $id, PDO::PARAM_INT);
$stmt->bindParam(2, $type, PDO::PARAM_STR, 256);
$stmt->bindParam(3, $fp, PDO::PARAM_LOB);
$db->beginTransaction();
$stmt->execute();
$db->commit();
}
catch(PDOException $ex)
{
$db->rollBack();
print $ex->getMessage()."\n";
}
foreach($db->query('SELECT id, contenttype, lengthb(imagedata) FROM images') as $row)
{
print $row[0].' '.$row[1].' '.$row[2]."\n";
}Displaying an image from a database
print "\n[Displaying an image from a database]\n";
try
{
$stmt = $db->prepare("SELECT contenttype, imagedata FROM images WHERE id = ?");
$id = 1;
$stmt->execute(array($id));
$stmt->bindColumn(1, $type, PDO::PARAM_STR, 256);
$stmt->bindColumn(2, $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
print 'Content-Type: '.$type."\n";
print 'size: '.file_put_contents($id.".png", $lob)."\n";
}
catch(PDOException $ex)
{
print $ex->getMessage()."\n";
}