PHP 5 Data Object (PDO) abstraction layer and Oracle

Source: Internet
Author: User
Tags odbc connection php database php error

The original developer at the data abstraction layer of a new PHP Data Object (PDO) briefly introduces this abstraction layer, focusing on running with Oracle.

PHP: 5.0 required
Other required: Oracle 8 or later client library
Download PDO for Oracle (Windows): php_pdo.dll, php_pdo_oci.dll
Download the PDO (Unix): pdo, pdo_oci for Oracle

About PDO

PHP is mainly a project completed by volunteers. Although there are a few fixed "core" developers, none of us are working full-time to develop PHP. In addition, we are located in different parts of the world. You can imagine how difficult it is to coordinate long-term development. Therefore, PHP is mainly developed based on the short-term demand of sudden whimsical individuals. There are also various reasons, some of which are experimental, and some are because "there is a job to hand in tomorrow ". Although PHP is usually improved at every step, in the long run, there is a lack of integrity-database expansion is an important example.

There is no real consistency between various data extensions (such as oci, mysql, postgresql, and mssql). In some cases, there is no real consistency within these extensions. Almost all of these extensions use different codes closely linked to the basic database API to complete the same type of tasks. In addition, because we (PHP core developers and extension developers) have very limited manpower, this makes the code more difficult to maintain and brings a lot of problems to PHP.

As PHP is becoming increasingly popular and successful, maintainers of major PHP database extensions attended the LinuxTag 2003 Conference in Germany. At the Conference, we exchanged views on the future of PHP. When discussing the randomness of PHP development, we have determined some goals for database access in PHP:

· Provides a lightweight, clear, and convenient API
· Unify the common features of different RDBMS databases, but do not exclude more advanced features.
· Provides optional abstract/compatibility with PHP scripts.

We have proposed the concept of this PHP Data Object (PDO) because we want to use Zend Engine 2 (the core of PHP 5) advanced object-oriented features provide better performance for this API.

The concept of the data abstraction layer in PHP is not new at all. querying "PHP database abstraction action" in Google will find about 83,200 matching items. It is almost the dream of many PHP developers, and its generation is partly attributed to our incomplete API. If you have tried to use a third-party abstraction layer to do anything really important, these abstraction layers are usually designed to be too powerful for the work at hand-either as they require a lot of learning before use or as slow interfaces, parameters must be called by a multi-layer script function before they can reach the database's own API. The preceding two representations usually exist.

Why are these abstract layers having such problems? These abstract layers are always trying to complete too many tasks, or even impossible tasks. We decided to take practicality as our goal, and only use some of the most common database API features as our foundation, so that the PDO driver can expose their product-specific features as regular extension functions.

Why use PDO?

Most people who have heard of rumors about database abstraction extensions immediately have doubts about PDO extensions-do we want to analyze SQL statements and convert them into corresponding back-end dialects? How do we deal with feature X or feature Y. Therefore, you may be surprised when you hear that we don't have to worry about it in PDO. We don't want to make everything completely unified, because we want to make this unified possible, you can only limit yourself to the lowest standard.

If PDO is not an abstract layer, is there any other reason why you should consider using it?

· Performance. From the very beginning, PDO learned from the success and failure of existing database expansion. Because the PDO code is brand new, we have the opportunity to design performance again to take advantage of the latest features of PHP 5.
· Capability. PDO is designed to provide common database functions as the basis and provide convenient access to the unique functions of RDBMS.
· Simple. PDO is designed to make it easy to use databases. The API does not forcibly intervene in your code and clearly shows the process of calling each function.
· Runtime scalability. The PDO extension is modular, allowing you to load drivers at the backend of your database at runtime without re-compiling or re-installing the entire PHP program. For example, the PDO_OCI extension replaces the PDO extension to implement the Oracle database API. There are also some drivers for MySQL, PostgreSQL, ODBC, and Firebird. More drivers are still under development.

You may want to know the comparison between PDO and other commonly used abstract layers, such as pear db or ADODB. In terms of API and performance, PDO is lighter than other common abstraction layers, but it is inferior to those abstraction layers to provide uniformity between the backend of each database, for example, the pear mdb 2 abstraction layer is used to handle a large number of portability problems.

Where can I obtain PDO?

PDO is provided through the PECL (pronounced "pee-kle", European language style), that is, the PHP extension library. If you are running a Linux computer, follow the instructions below to set it. Later, the installation details are provided on Windows.

Note that the PDO and its drivers are currently in the "alpha" State; this means we will reasonably ensure there are no major defects, but this package is not fully functional-we need to add a lot of functionality. Although we encourage you to test this package, it is not recommended to use it for production at this stage.

Unix/Linux Installation

If you have not tried PHP 5 before, take a moment to read the "news" and various statements. On UNIX computers, you may need to install or upgrade libxml2. Without libxml2, the "pear" package management tool cannot run, and you may encounter many difficulties when installing PDO. Obtain PHP 5 and compile and install it. Make sure that the specified prefix is not/usr/local/, so that it will not conflict with PHP 4 installation:

%./Configure -- prefix =/usr/local/php5 -- with-zlib [specify other options here]
% Make install


Now you can use the pear tool to obtain and install PDO and the Oracle driver for PDO. Because PDO is currently marked as alpha, the pear tool does not download the package by default. Add the suffix "-alpha" after the package name to notify the pear tool to install alpha:

% PATH = "/usr/local/php5/bin: $ PATH"
% Pear install PDO-alpha


You need to inform PHP to load the PDO driver from the PHP. ini file dedicated to php 5. If you use the same prefix as I used, PHP will search for the php. ini file in/usr/local/php5/lib/php. ini. Add the following lines to the file:

Extension = pdo. so

Now you need to obtain a specific database driver. For Oracle, this specific program is called PDO_OCI. In shell, type:

% Pear install PDO_OCI-alpha

This driver also needs to be loaded from the php. ini file; Add the downstream to the row added above:

Extension =

Check now to make sure it can run:

% Php-m

In the module list, you should see PDO and PDO_OCI.

What's wrong with the firewall?

If you are behind the firewall, you may encounter some problems when using the pear installer to obtain the package. In this case, you can follow the instructions below to manually download and install these packages:

% Wget
% Pear install PDO-0.1.1.tgz

[Add extension = pdo. so to php. ini]

% Wget
% Pear install PDO_OCI-0.1.tgz

[Add extension = to php. ini]

In both cases, you must first call "pear install" (followed by the downloaded Real Package). The version number in the preceding example is the latest in this article, but it will change as development continues.

Windows Installation

If you are running Windows, follow the instructions below:

· Get PHP 5 from the and decompress it to C: \ php5.
· Get PDO and PDO_OCI from and respectively, and put them into C: \ php5 \ ext. Alternatively, you can find all these PDO drivers and all Windows versions of PECL packages in the "PECL module set for PHP 5.0.0" zip file listed on the PHP 5 download page.
· Edit the C: \ php5 \ php. ini file and add the following content:

Extension = php_pdo.dll
Extension = php_pdo_oci.dll

When editing the php. ini file, it is important to load the PDO extension before any other PDO driver. Otherwise, the initialization fails (in this case, an error occurs ).

If the Windows directory contains a global PHP. ini file of php 4, you may encounter problems. The best solution is to move the php. ini file so that it is in the same folder as PHP 4 SAPI to isolate PHP 4 installation; for example, move it to the same folder as php4apache. dll in the same folder. Note that not all documents in PHP 5 are up-to-date. The recommended installation process is described above, as stated in the install.txt file, do not copy any DLL to the windows folder or system folder-any content is self-contained. If you are running apache and encounter an error where DLL cannot be loaded, check whether C: \ php5 is added to PATH. Also, note that the CGI version of PHP 5 is now named php-cgi.exe.

Connect to PDO

First, create an instance of the PDO class and use it as a database handle. It doesn't matter which basic driver to use; you always need to use the PDO class name. The first parameter of the constructor is the data source name (DSN), the second parameter is the user name, and the third parameter is the password of the user name. The PDO naming convention of DSN is the name of the PDO driver, followed by a colon, followed by optional driver-specific information. In our example, the OCI driver is loaded without specifying any other information. This will use the default database. For other drivers, such as ODBC drivers, all content after the first colon will be used as odbc dsn. The MySQL driver will also explain its DSN in different ways.

If the driver cannot be loaded or the connection fails, a PDOException is thrown so that you can decide how to handle the fault best.

<? Php
Try {
$ Dbh = new PDO ("OCI:", "scott", "tiger ");
} Catch (PDOException $ e ){
Echo "Failed to obtain database handle". $ e-> getMessage ();

You can specify two optional parameters in the connection string. The first parameter is the database name and the second parameter is the character set. These parameters correspond to the third and fourth optional parameters, you may have used the last two parameters in the oci8 Extension function ociconnect () or ociplogon. To connect to a specific database using a specific character set, you can perform the following operations:

<? Php
Try {
$ Dbh = new PDO ("OCI: dbname = accounts; charsets = UTF-8", "scott", "tiger ");
} Catch (PDOException $ e ){
Echo "Failed to obtain database handle". $ e-> getMessage ();

It is not helpful to omit the try... catch control structure. If no exception handling is defined at a higher level of the application, the script will be terminated if a database connection cannot be established.

Connection Management

Currently, PDO does not perform any connection management. Therefore, each "New PDO" Call creates a new database connection. This connection will be released when the $ dbh variable is out of bounds or when you specify a NULL value for it.

<? Php
Try {
$ Dbh = new PDO ("OCI: dbname = accounts; charsets = UTF-8", "scott", "tiger ");
} Catch (PDOException $ e ){
Echo "Failed to obtain database handle". $ e-> getMessage ();
// Perform operations on the database here

// Now the connection is finished. Release the connection.
$ Dbh = null;

We plan to add the connection cache function for PDO in the near future. In terms of the current oci8 extension, the connection to the existing server will be reused and idle logins will be reused in these connections. When running in cache connection mode, when $ dbh is released as shown in the code snippet above, the login will be marked as reusable by other connections.

If you use an ODBC driver to access Oracle, You may be happy to note that the PDO_ODBC driver supports the ODBC connection pool by default.


The best way to understand a programming API is to use it, so let's take a look at the demo that comes with it to learn how to Perform Batch Update (the Code is as follows ).

<? Php

// Create a PDO database handle object
// The 'oss: 'string specifies that the oci driver shocould be used
// You cocould use 'oss: dbname = name' to specify the database name.
// The second and third parameters are the username and password respectively
$ Dbh = new PDO ('oss: ', 'Scott', 'tiger ');

// Create a test table to hold the data from credits.csv
$ Dbh-> exec ("
Create table credits (
Extension varchar (255 ),
Name varchar (255)

// Start a transaction
$ Dbh-> beginTransaction ();

// Prepare to insert a large quantitiy of data
$ Stmt = $ dbh-> prepare ("insert into credits (extension, name) VALUES (: extension,: name )");

// Bind the inputs to php variables; specify that the data will be strings
// With a maximum length of 64 characters
$ Stmt-> bindParam (': extension', $ extension, PDO_PARAM_STR, 64 );
$ Stmt-> bindParam (': name', $ name, PDO_PARAM_STR, 64 );

// Open the. csv file for import
$ Fp = fopen('credits.csv ', 'R ');
While (! Feof ($ fp )){
List ($ extension, $ name) = fgetcsv ($ fp, 1024 );
$ Stmt-> execute ();
Fclose ($ fp );

// Commit the changes
$ Dbh-> commit ();


Since we have successfully connected to Oracle, now we can create a table to save some data. For this example, we use some PHP extensions and their authors, and input the content into a database. The exec () method of the database handle object can be used to issue a quick one-time query that does not return the result set. Therefore, we use this method to issue a create table query here.

To make the example more natural, I extracted the extension and its author information from the PHP source code and stored it in a CSV file (see "related attachment: credits.csv "). This represents a common situation: importing data in batches from CSV files. In our example, we fully utilize the Oracle pre-processing statement and bind parameters to obtain an efficient data import script. Before describing this example, it is necessary to understand how PDO processes transactions.

Transaction Processing in PDO

Oracle has a sensitive default operation mode: When you connect, it will be in an implicit transaction, and the changes will not take effect until the transaction is committed. In addition to the standard advantages of transaction processing (atomicity, consistency, isolation, and durability-ACID), the database server does not need to re-build indexes and other internal structures after each update; it can be delayed after submission. This will accelerate code execution. Oracle is really good.

Unfortunately, not every database vendor supports transaction processing, and because PDO is designed to support these transactions in a relatively portable manner, therefore, it runs in auto-submit mode by default. When the automatic submission mode is enabled, the database driver implicitly submits each successful update. When you call $ dbh-> beginTransaction (), the automatic submission is closed until $ dbh-> commit () or $ dbh-> rollBack () is called () it will be re-enabled, depending on how your code is written. If the underlying driver does not support transaction processing, a PDOException is thrown.

If a problem occurs and a PHP error occurs, your script exits and the transaction is waiting for approval. Or when you close the database handle, PDO automatically calls $ dbh-> rollBack () for any pending transactions (). This behavior reduces the possibility of submitting undefined or corrupted data to the database, which is the standard semantics used to process abandoned transactions.


Pre-processing statements and stored procedures

PDO supports using the placeholder syntax for Oracle style naming to help set variables to preprocessing statements in SQL (similar to ocibindbyname () in the oci8 extension ). PDO also provides name placeholder Simulation for other databases (such as ODBC). It can even simulate preprocessing statements and bind parameters for databases (such as MySQL) that are not born to support this concept. This is a positive step forward for PHP, because it enables developers to write "enterprise-level" database applications using PHP without having to pay special attention to the capabilities of the database platform.

The PDO preprocessing statement is very simple. You can call the prepare () method of the database handle. It returns a statement handle object, and you can use this object to bind parameters and execute statements. In this example, we will define two placeholder names: ": extension" and ": name. the PHP extension name in the CSV file corresponds to the name of one of the authors.

$ Stmt = $ dbh-> prepare ("insert into credits (extension, name) VALUES (: extension,: name )");

After the statement is preprocessed, we use the bindParam () method to associate these naming parameters with the PHP variable names "$ extension" and "$ name" (which are associated with ocibindbyname () ). We will also notify Oracle that the data will be formatted as a string with a maximum length of 64 characters.

$ Stmt-> bindParam (': extension', $ extension, PDO_PARAM_STR, 64 );
$ Stmt-> bindParam (': name', $ name, PDO_PARAM_STR, 64 );

Now we are ready to insert data-we only need to open the CSV file and obtain data from it. You can perform this operation quite simply by using the fopen () and fgetcsv () functions. Then, we can use the PHP list () constructor to directly specify the CSV columns to the variables "$ extension" and "$ name ". Because these variables have been bound to the statement, all we need to do now is call the execute () method of the statement object to execute the insert. This method is convenient and fast-there are only two rows in each iteration loop during transaction processing. At the end of the file, we can use the commit () method of the database handle to submit these changes immediately.

If you only want to pass the input parameters and many of them need to be passed, you will find the shortcut syntax shown below very helpful; this syntax allows you to save calls to $ stmt-> bindParam.

$ Stmt = $ dbh-> prepare ("insert into credits (extension, name) VALUES (: extension,: name )");
$ Stmt-> execute (array (': extension' => $ extension,': name' => $ name ));

You can also use bindParam to set input/output parameters for stored procedures. The syntax is identical, but the query is different. The following code demonstrates how to call a stored procedure named "sp_add_item" to set $ item_name for the input, and then update $ error_code when the stored procedure returns.

$ Stmt = $ dbh-> prepare ("begin sp_add_item (: item_name,: error_code); end ");
$ Stmt-> bindParam (': item_name', $ item_name, PDO_PARAM_STR, 12 );
$ Stmt-> bindParam (': error_code', $ error_code, PDO_PARAM_STR, 12 );
$ Stmt-> execute ();


Capture Data

Using PDO to capture data is similar to inserting or updating data, but after you execute the query, you will repeatedly call the fetch () method to obtain the next row of the result set. The simplest case is as follows. It is worth noting that you can also bind parameters to queries to control content such as the WHERE clause; the syntax for executing this operation is exactly the same as the bindParam () code we have seen.


$ Stmt = $ dbh-> prepare ("SELECT extension, name from CREDITS ");
If ($ stmt-> execute ()){
While ($ row = stmt-> fetch ()){
Print_r ($ row );

PDO supports different crawling policies that differ in convenience and performance. By specifying one of the following options as a parameter of the fetch () method, you can change the return value to adapt to your Syntax:

· PDO _ FETCH_NUM-an array indexed by column position is returned for each row capture, and is base on 0 (the first column is 0th elements ).

While ($ row = $ stmt-> fetch (PDO_FETCH_NUM )){
Printf ("Extension % s, by % s <br>", $ row [0], $ row [1]);

· PDO _ FETCH_ASSOC-each row is crawled Based on the column name in the row set and an array indexed by column name is returned.

While ($ row = $ stmt-> fetch (PDO_FETCH_ASSOC )){
Echo "Extension $ row [EXTENSION] by $ row [NAME] <br> ";

· PDO _ FETCH_BOTH-an array indexed by column position and by column name is returned for each row capture. That is, the direct combination of the above two cases. If the capture mode is not specified, this mode is the default mode.
· PDO _ FETCH_OBJ-An anonymous object is returned for each row capture. Its attribute name corresponds to the column name.

While ($ row = $ stmt-> fetch (PDO_FETCH_ASSOC )){
Echo "Extension {$ row-> EXTENSION} by {$ row-> NAME} <br> ";

· PDO _ FETCH_LAZY-each row captures and returns an overloaded object of the referenced statement object. This "looks" like a combination of PDO_FETCH_OBJ and PDO_FETCH_BOTH. These variables are created only when you access PHP variables in the script.
· PDO _ FETCH_BOUND-captures each row and returns TRUE. This method is very useful when you bind an output column. It can avoid creating any unnecessary arrays or objects. (See the following example ).

No matter which crawling policy you use, when no other row can be crawled, The fetch () method returns FALSE.

Now I want to talk about some tips. If you need to adjust the script performance at last, these skills may be helpful to you. But let's give you one piece of advice: avoid immature optimization like avoiding plague. You should always choose the most clear and maintainable solution. Remember, in a typical Web application, you cannot measure the differences between different capture modes unless the script processes many lines. I will repeat it again: the performance difference between capture modes is very small-Please use the mode that best suits your code.

Remember that using PDO_FETCH_NUM is the least expensive, because accessing column data is only a simple numerical query. PDO_FETCH_OBJ enables you to use the OO syntax to access the dataset columns as object attributes. However, each attribute access involves an additional hash query, the cost of using it is basically the same as that of PDO_FETCH_ASSOC. In each of these modes, the entire row is copied to occupy a little more memory.

Many database drivers capture and cache a certain number of rows in advance. Every time PHP accesses a column in such a row, it needs to copy it to its own dedicated memory area. If your query involves many rows and you only need to access specific columns of a given row based on some complicated logic, you will find that PDO_FETCH_LAZY is a useful method to avoid using a lot of memory, because it only copies a given column when you access it. When using this method, note that each fetch () the crawled "inert object" is the same object used during each iteration (to reduce the overhead of each creation/destruction ). This implies that you cannot simply store the object for future comparison, because it will still reference the current row of the statement-the part you need to manually copy.

The last mode is PDO_FETCH_BOUND, which tells PDO that you have bound all columns to the PHP variable, in addition, you do not need to perform any operations except to notify you when it reaches the end of the row set. The bound output column is similar to the bound input parameter in concept, but the bound output column can be used for all database drivers. You can bind the PHP variable to the name column. PDO updates the variable every time execute () is called. This technology can be used to shave off some virtual machine operation codes for each column and line in the result set (this code is slower than the native code ). The disadvantage of this technology is that it may make your code difficult to trace (also known as the WTF coefficient is high), you need to be careful when using variable names. The following code illustrates how to bind an output column. Note that you do not need to specify PDO_FETCH_BOUND to use $ stmt-> bindColumn (); PDO_FETCH_BOUND is only an optimization for your understanding that only bound values can be used.

$ Stmt = $ dbh-> prepare ("SELECT extension, name from CREDITS ");
If ($ stmt-> execute ()){
$ Stmt-> bindColumn ('extension', $ EXTENSION );
$ Stmt-> bindColumn ('name', $ NAME );
While ($ stmt-> fetch (PDO_FETCH_BOUND )){
Echo "Extension: $ extension, Author: $ name \ n ";



Case-sensitive Columns

PDO is designed to make scripts that use portable SQL run well and can be transplanted. All queries mentioned in this article (except for calling Stored Procedures) have the same running performance when using any PDO driver-including all bound input variables and bound output columns.

But there is a conversion problem-when you use PDO_FETCH_ASSOC to capture data, different drivers will return different column names in different ways-some will convert the column names to uppercase, and some to lowercase, some will make it show the style specified in the query. This is a potential problem for PHP scripts because the array keys are case sensitive. PDO provides a compatibility attribute to help standardize the script results. The following small code snippet is the portable version of the above PDO_FETCH_BOUND example, because the setAttribute () method call instructs PDO to convert all the retrieved column names to uppercase:

$ Dbh = new PDO ('oss: ', 'Scott', 'tiger ');
$ Dbh-> setAttribute (PDO_ATTR_CASE, PDO_CASE_UPPER );
Stmt = $ dbh-> prepare ("SELECT extension, name from CREDITS ");
If ($ stmt-> execute ()){
$ Stmt-> bindColumn ('extension', $ EXTENSION );
$ Stmt-> bindColumn ('name', $ NAME );
While ($ stmt-> fetch (PDO_FETCH_BOUND )){
Echo "Extension: $ extension, Author: $ name \ n ";

In addition to PDO_CASE_UPPER, PDO_CASE_LOWER (which converts the column name to lowercase) and PDO_CASE_NATURAL (which is the default option to keep the column in the form returned by the database driver ).

Handle errors and errors

Another challenge for porting scripts is to handle different types of error messages returned from various database processors. Some databases have poor support for programmatic error handling, other databases have rich error codes. As long as it works, PDO will provide a unified error code for your script, so that you do not have to worry about portability. Of course, PDO also provides the driver with native error code and error messages, in case you need to use it for diagnosis or the error code ing is incomplete.

Another consistency problem that troubles PHP database extensions is the consistency of error handling policies: some extensions return error code that requires you to manually capture error strings, while some other extensions only issue PHP warnings. PDO allows you to select one of the following three different error handling policies:

This is the default mode. It only uses the statement and the errorCode () and errorInfo () Methods of the database handle object to set the error code to be checked.

If (! $ Dbh-> exec ($ SQL )){
Echo $ dbh-> errorCode (). "<BR> ";
$ Info = $ dbh-> errorInfo ();
// $ Info [0] ==$ dbh-> errorCode () Unified error code
// $ Info [1] is the driver-specific error code
// $ Info [2] is the driver-specific error string

In addition to setting error codes, PDO also issues a PHP warning. You can use a common PHP error handler to capture this warning, and centrally apply any error handling/record policies you have prepared for the application, or simply display the error in the browser (useful during internal testing ).
In addition to setting the error code, PDO throws a PDOException and sets its attribute to include the error code and information. Then, you can capture the exception at a higher level of the code and use the global exception handler to capture the exception, or terminate the script without processing it (at this time, any pending transactions will be rolled back ).

Try {
$ Dbh-> exec ($ SQL );
} Catch (PDOException $ e ){
// Display warning messages
Print $ e-> getMessage ();
$ Info = $ e-> errorInfo;
// $ Info [0] === e-> code; uniied error code
// $ Info [1] is the driver-specific error code
// $ Info [2] is the driver-specific error string

Note that, compared to warnings or exceptions, silent mode has the least resources for running errors, but to get this speed, you sacrifice some simplicity and become a little complicated.

The unified error code table currently contains the following constants: PDO_ERR_NONE, PDO_ERR_CANT_MAP, PDO_ERR_SYNTAX, PDO_ERR_CONSTRAINT, begin, primary, primary, PDO_ERR_MISMATCH, primary, PDO_ERR_DISCONNECTED.

The meaning represented by these constants can be understood literally, except for the PDO_ERR_CANT_MAP code. This is a PDO-specific code, that is, it cannot map the driver-specific code to the unified error code, therefore, you should query the specific driver code returned by the errorInfo () method to obtain more information.

Data Type

PDO is of unknown type to some extent, so it prefers to represent data as a string rather than converting it to an integer or double-precision type. At this point, you may be confused about this, but the reason is very simple: the string type is the most accurate type, which has the widest application scope in PHP; premature data conversion to integers or double precision may result in truncation or rounding errors. By extracting data as strings, PDO provides some script control for you. You can use common PHP conversion tools (such as conversions and implicit conversions during mathematical operations) to control how to perform conversion and when to perform conversion.


If a column in the result set contains a NULL value, PDO maps it to a PHP null value. Oracle converts NULL strings to NULL when returning data to PDO, but no other database supported by PHP does. This causes portability problems. PDO provides a driver-level property PDO_ATTR_ORACLE_NULLS that simulates this behavior for other data drivers:

$ Dbh = new PDO ('oss: ', 'Scott', 'tiger ');
$ Dbh-> setAttribute (PDO_ATTR_ORACLE_NULLS, true );
// In any statements opened from $ dbh
// Empty strings are converted to NULL


POD Status Quo and Future

PDO is still quite immature, but it will become mature quickly. At the time of writing this article, everything I mentioned in this article can be applied to Oracle 8 or later (tested on Oracle 8.0 and 9.2) through the PDO_OCI driver ).

The following features are planned to be available soon:

1. Use LOB support for PHP stream. By binding parameters, you can pass any stream resources (such as files, sockets, HTTP resources, compressed/filtered streams) as input or output parameters to the query running on LOB. Similarly, output parameters of the LOB type are expressed as PHP streams, so you can use fread (), fwrite (), fseek (), and other stream functions to access these parameters. In this case, there is no LOB support in PDO.
2. Persistent connections and cache preprocessing statements. Persistent connections prevent you from enabling or disabling database server connections when each page hits. The cache pre-processing statement is another step forward, which enables you to persistently maintain the pre-processing version and database handle of the query.
3. cursor. Currently, PDO only provides forward read-only cursors, but in the future it will provide scroll cursors (supported by the Basic driver), REF-CURSOR, and CURSOR-based location update, and updatable scroll cursors.

We want to enable PHP extensions by default in PHP 5.1 (far from this target), but before that, we want to make PDO run stably at PHP 5.0 release, however, the pressure in our daily work is a little too long. At the same time, the release of PDO through PECL enables us to respond when we receive the problem report and release the fix version according to the schedule different from the PHP 5.0 release schedule, therefore, you can use PDO before PHP 5.1 is released.

We need your feedback

If you have tried PDO and found any problems, please use our Error Tracking software to report it to us. If you are using an Oracle driver, use this page:

Http:// Package = PDO_OCI

If you are using another driver, replace PDO_OCI in the URL with its name.

If you encounter problems when using PDO, have questions about certain features, or have feature requests, contact the If you want to, of course, you can also directly contact me (, but please note that I receive a lot of emails about PHP every day; you may find that you will receive a response faster if you contact the previous email list first.

About the author
Wez Furlong is the technical director of Brain Room Ltd., where he not only uses PHP for Web development, but also uses it as an embedded script engine for Linux and Windows applications and systems. Wez is the core developer of PHP. It often contributes to SQLite, COM/. Net, ActivePHP, mailparse, and Streams APIs. It is the "head" of the PHP extended community library ". His consulting company's webpage is

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.