• Aucun résultat trouvé

Query Methods

Dans le document PHP OBJECT-ORIENTED (Page 168-171)

Look again at Listing 15-4. It includes the five methods for creating result sets. The buffered and unbuffered methods are fairly self-explanatory—you are probably quite familiar with the equivalent MySQL functions. However, MySQL (prior to the MySQL improved extension) has nothing to match the singleQuery, queryExec, or arrayQuery methods. Let’s look at these methods in more detail.

The singleQuery method is a recent addition, and the PHP site warns that it is not currently documented. Let’s carry on regardless because this method looks especially useful for those situations where a query returns only one row—when using the COUNT function to return the number of records in a table, for example. Here’s one view of how this method ought to behave: This method returns only one record, and no result set is created. If the second argument is false, the value returned is an array of the first row. If the sec-ond argument is true, then only the first column of the first row is returned, and it is returned as a scalar value.

This speculation may make the best sense of how this method ought to work, but it doesn’t describe what actually happens. In fact, this method only ever returns the first column and any number of rows. If the second argument is false, then an array is returned; if the second argument is true and only one row is returned, a scalar is returned. On the PHP site, this second argument is identified as bool first_row_only and the return type is identified as an array. It looks like the return type should be mixed. In any case, this method doesn’t yet work the way it ought to. We were warned.

There is no requirement that you use the singleQuery method instead ofquery. As with MySQL, you can always create a result set and then use the appropriate fetch function to retrieve the value of the first row or a specific field. But why return an object or an array when all that’s needed is the value of one column? You may use the singleQuery method for any kind of query—

data manipulation or otherwise—but it was designed specifically for situa-tions where a single value or single column is returned, and is presumably optimized for this situation.

As you can see, there is also an arrayQuery method. Like the singleQuery method, this method allows us to directly copy results into an array, bypassing the intermediate step of creating a result set. This method is best used when a limited number of records are returned.

MySQL versions prior to 4.1 have no equivalent to the queryExec method of SQLite because queryExec is specifically designed for use with multiple queries.

Multiple, semicolon-separated queries may be passed as a single query string to queryExec. (The install script uses this method to create the tables, triggers, and views and to insert records into the tblresources table.) This method gives significant performance improvements over repeated querying and performs

Ex t en di ng SQL it e 149 the same job as the MySQL-improved (the mysqli functions added to PHP 5 to support MySQL 4.1) method, mysqli_multi_query. If you like, you can of course use this method to execute a single query.

query

Use of this method to create an SQLiteResult object is shown in Listing 15-5.

$db = new SQLiteDatabasePlus('resources.sqlite');

//alphabet view

$strsql = "SELECT * FROM alphabet";

//use buffered result set to get number of rows

$result = $db->query($strsql);

//create alphabet here if($result->numRows() > 0){

echo get_alphabet($result);

}

Listing 15-5: query method returns a buffered result set

Remember, an SQLiteResult is buffered so you can use the numRows method with this result set. It is also iterable, so this result set may be used in a foreach loop. In this, SQLite differs from MySQL. Because SQLiteResult implements Iterator, all the iterator methods are present—rewind, next, valid, and current. These methods can be used directly, but their real purpose is to allow an SQLite result set to be used in a foreach loop in exactly the same way that you might use an array. (As you might expect, the rewind method can’t be applied to an unbuffered result set.) Only this method and the unbuffered query method return a result set object.

unbufferedQuery

There is no need to buffer the result set returned in Listing 15-6.

try{

$db = new SQLiteDatabasePlus('../dbdir/resources.sqlite');

$type="Edit";

//retrieve from db

$strsql = "SELECT * FROM tblresources ".

"WHERE id = '$id'";

//get recordset as row

$result = $db->unbufferedQuery($strsql);

$row = $result->fetch();

//can't use below because returns first column only //$row = $db->singleQuery($strsql, false);

// assume vars same as fields while(list($var, $val)=each($row)) {

Listing 15-6: The unbufferedQuery method

This listing shows an unbuffered query. In this case, a functional singleQuery method would be preferable because we know that only one record will be returned. However, given the problems with singleQuery, we use the unbufferedQuery method of an SQLiteDatabase object to create a result set object and then use the fetch method to copy the first row into an array.

arrayQuery

The PHP site warns against using the arrayQuery method with queries that return more than 45 records (a somewhat arbitrary number perhaps, but this method stores results in memory so returning a large number of records can exhaust memory). We’ve used this method in Listing 15-7.

$db = new SQLiteDatabasePlus('../dbdir/resources.sqlite');

$db->createFunction('class_id','set_class_id',0);

$sql = "SELECT id, url, email, ".

"(precedingcopy || ' ' || linktext || ' ' || followingcopy) ".

"AS copy, linktext, reviewed, class_id() AS classid ".

"FROM tblresources ".

"ORDER BY id DESC ".

"LIMIT $recordoffset,". PERPAGE;

//use arrayQuery

$resultarray = $db->arrayQuery($sql);

...

Listing 15-7: Using arrayQuery

As you can see, we know exactly how many records are returned because our SQL has a LIMIT clause. Again, this method allows us to bypass creation of a result set.

singleQuery

The code below uses the singleQuery method and does exactly what we need—it returns a single scalar value rather than a result set or an array.

$totalrecords = $db->singleQuery('Select COUNT(*) FROM tblresources', true);

queryExec

This method is commonly used to process a transaction. Use the command-line command .dump to dump your database or view the file dump.sql. You’ll see that it is formatted as a transaction. You can recreate an entire database by passing this listing as a string to the queryExec method, as we have done with the install script, db_install_script.php.

The ability to perform multiple queries using one string does raise security issues. When using this query method, it is especially important to filter data in order to avoid a possible SQL injection attack. For more details, see php|architect’s Guide to PHP Security.1

1 Ilia Alshanetsky, php|architect’s Guide to PHP Security (Marco Tabini & Associates, Inc., 2005), 73.

Ex t en di ng SQL it e 151

Dans le document PHP OBJECT-ORIENTED (Page 168-171)