• Aucun résultat trouvé

Code Changes

Dans le document PHP OBJECT-ORIENTED (Page 178-181)

As usual, a complete version of the code discussed in this application is avail-able from the book’s website. The directory structure for the files accompa-nying this chapter is the same as those for Chapter 15, so you shouldn’t have trouble finding your way around. Also, as usual, I won’t reproduce all the code in this chapter, only relevant sections. We’ll start by looking at the constructor.

Using PDO 159 NOTE The application we developed in Chapter 15 uses version 2 of SQLite. Take this

oppor-tunity to upgrade to SQLite version 3, since PHP 5.1 supports this version. It’s appre-ciably faster than version 2 and handles concurrency better. However, the database format has changed; versions 2 and 3 are incompatible. This is only a minor inconvenience.

If you want to get off to a quick start, install the database by running the db_install _script.php file found in the dbdir directory. This will create an SQLite version 3 database for you. Otherwise, you may download the command-line version of SQLite 3 from the SQLite website, and then see the section “Getting Started” on page 141 for details about using a database dump to install a database. The PDO driver for SQLite version 2 doesn’t support the sqliteCreateFunction method, so upgrading is required if you want to use this method. Matching the version of the command-line tool with the version of SQLite supported by PHP is equally important in this chapter, because of version incompatibilities. For example, a database created at the command line using SQLite version 3.5.5 will not work properly with the current SQLite PDO driver.

Constructing a PDO Object

When constructing a PDO database or connection object, a Data Source Name (DSN) is passed as a parameter. A DSN is made up of a driver name, followed by a colon, followed by database-specific syntax. Here’s how to create a connection to an SQLite database:

$pdo = new PDO('sqlite:resources.sqlite');

A PDO object is constructed in the same way as an SQLiteDatabase object except that the driver name must precede the path to the database and be separated from it by a colon.

The createFunction Method

You may recall that one of the deficiencies of SQLite was the lack of built-in functions, especially with respect to date manipulation. We were able to over-come this deficiency by adding functions to SQLite using the createFunction method. Fortunately for us, the developers of PDO have seen fit to incorporate this capability by including the SQLite-specific method sqliteCreateFunction. This saves us some work but also reduces the “abstractness” of the PDO layer—

but more about this later.

Exceptions

In Chapter 15 we extended the SQLiteDatabase class in order to throw an exception if a query failed. For that reason we overrode the five existing query methods. The same effect can be achieved with PDO by using only one line of code:

$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Calling setAttribute against a PDO database connection in this way causes any failed attempt at querying the database to throw a PDOException. This is a very succinct way of dealing with one of the shortcomings of the

SQLite classes. We quickly reap all the benefits of throwing exceptions without having to extend the SQLite database class.

Methods of SQLiteDatabasePlus

Because a PDO connection can be configured to throw exceptions, we don’t need the query methods of our derived class SQLiteDatabasePlus. However, the utility methods we added are another matter. The only way to use these methods is to rewrite them as functions. They convert fairly readily, and the metadata queries they employ work as before. The only real difference is that as functions they are not quite as convenient to use. I won’t reproduce them here, but they can be found in the dbfunctions.inc file included in this chap-ter’s downloads.

Escaping Input

The cleanData utility method of our derived class incorporated the sqlite_escape_string function to escape input before insertion into the database. The equivalent PDO method is quote. Be aware that this method not only escapes single quotation marks, but also encloses the item quoted within quotation marks. If you need to manipulate data prior to inserting it, quote should only be called immediately prior to insertion. For portability reasons, the PHP site recommends using prepare rather than quote. We’ll investigate this method more fully when we discuss statements, in the section

“Additional Capabilities of PDO” on page 161.

Query Methods

One of the attractions of SQLite is its variety of query methods. If you need a quick refresher, see the section “Query Methods” on page 148. In this section we’re going to compare SQLite’s query methods to what’s available using PDO.

The difference between the object models of SQLite and PDO makes a direct comparison a bit awkward. Principally, querying a PDO connection returns a statement object, and this statement effectively becomes a result set once it is executed. As already mentioned, we’ll cover statements in the section “Additional Capabilities of PDO” on page 161, but for the moment we can treat them as identical to result sets.

The five query methods of SQLite are singleQuery, execQuery, arrayQuery, query, and unbufferedQuery. We’ll discuss each SQLite query method in turn.

The singleQuery method returns a single column as an array, bypassing the need to create a result set. To mimic it we would use a PDO query to return a statement and then call fetchColumn against this statement. The fetchColumn method can return any column in the current row.

The execQuery method of an SQLite result set can execute multiple, semicolon-separated queries. PDO can easily mimic this behavior—in fact this is something that statements excel at.

As you might expect, returning an array in the fashion of arrayQuery is also easily handled by PDO by calling the fetchAll method against a statement.

The two remaining query methods of SQLite, query and unbufferedQuery, return SQLiteResult and SQLiteUnbuffered objects, respectively. PDO statements are comparable to unbuffered result sets rather than buffered ones, so the

Using PDO 161 unbuffered behavior is easily reproduced. Our SQLite application uses buffered result sets in cases where we need to know that there are records returned or where the specific number of records is required. To buffer records using PDO you can use the fetchAll method of a statement to return an array. A record count can be obtained by using the count function on the returned array. Alternately, calling the function empty on the statement returned by a query will determine whether there is at least one record.

In general, when querying the database, it looks like some efficiencies have been lost. What is a single process using SQLite becomes a two-step process with PDO. Using two methods instead of one can make code more complicated. However, as we’ll soon see, there are some important advantages to the PDO methods, and in some cases this two-step process can be simplified.

Dans le document PHP OBJECT-ORIENTED (Page 178-181)