MDB2

The goal here is to right database agnostic code in PHP. The PEAR package MDB2 » can help.

Run the following command to install MDB2.

# pear install mdb2

Example of querying a database and returning a row via a loop.

<?php
$dsn = "mysql://root:ilovesiam@localhost:3306/bookmarks";
$options = array ("persistent" => true);

# Creates an object and will connect to the database.
#$mdb2 =& MDB2::connect($dsn);

# Creates an object, but will not establish a connection until it's needed.
$mdb2 =& MDB2::factory($dsn);

# Singleton is like factory() but it makes sure that only one MDB2 object exists
# with the same DSN. If the requested object exists, it's returned; otherwise a
# new one is created.
#$mdb2 =& MDB2::singleton($dsn);

$mdb2->setFetchMode(MDB2_FETCHMODE_ASSOC);

// execute a query
$sql = 'SELECT * FROM people';
$result = $mdb2->query($sql);

// display first names
while ($row = $result->fetchRow()) {
 echo $row['name'], '
'
;
}

// release resources
$result->free();

// disable queries
$mdb2->setOption('disable_query', true);

// delete the third record
$id = 3;
$sql = 'DELETE FROM people WHERE id=%d';
$sql = sprintf($sql, $mdb2->quote($id, 'integer'));
echo '<hr />Affected rows: ';
echo $mdb2->exec($sql);

// close connection
$mdb2->disconnect();
?>

Executing Queries

To execute any query, you can use the query() or exec() methods. The query() method returns an MBD2_Result object on success, while exec() returns the number of rows affected by the query, if any. So exec() is more suitable for queries that modify data.

While you can basically perform any database operation with query(), there are other methods, discussed later, that are better suited for more specific common tasks.

http://www.installationwiki.org/MDB2#Executing_Queries »

You also have access to the number of rows and the number of columns in a result set.

$sql = 'SELECT * FROM people';
$result = $mdb2->query($sql);
echo $result->numCols(); // prints 4
echo $result->numRows(); // prints 3

query*() Shortcuts

You have at your disposal the methods queryAll(), @queryRow(), queryOne(), and queryCol(), which correspond to the four fetch*() methods explained above. Here's an example to illustrate the difference between the query*() and the fetch*()@@ methods:

// the SQL statement
$sql = 'SELECT * FROM people';

// one way of getting all the data
$result = $mdb2->query($sql);
$data = $result->fetchAll();
$result->free(); // not required, but a good habit

// the shortcut way
$data = $mdb2->queryAll($sql);

http://www.installationwiki.org/MDB2#query.2A.28.29_Shortcuts »

Quoting Values and Identifiers

The different RDBMS use different quoting styles (for example single quotes ' as opposed to double quotes ") and also quote different data types inconsistently. For example, in MySQL you may (or may not) wrap integer values in quotes, but for other databases you may not be allowed to quote them at all. It's a good idea to leave the quoting job to the database abstraction layer, because it "knows" the different databases.

MDB2 provides the method quote() for quoting data and quoteIdentifier() to quote database, table, and field names. All the quotes MDB2 inserts will be the ones appropriate for the underlying RDBMS. An example:

$sql = 'UPDATE %s SET %s=%s WHERE id=%d';
$sql = sprintf( $sql,
 $mdb2->quoteIdentifier('people'),
 $mdb2->quoteIdentifier('name'),
 $mdb2->quote('Eddie'), // implicit data type
 $mdb2->quote(1, 'integer') // explicit type
 );

If you echo $sql in MySQL you'll get:

UPDATE `people` SET `name`='Eddie' WHERE id=1

In Oracle or SQLite the same code will return:

UPDATE "people" SET "name"='Eddie' WHERE id=1

As you can see in the example above, quote() accepts an optional second parameter that sets the type of data (MDB2 type) to be quoted. If you omit the second parameter, MDB2 will try to make a best guess for the data type.

http://www.installationwiki.org/MDB2#Quoting_Values_and_Identifiers »

Iterators

MDB2 benefits from the Standard PHP Library (http://php.net/spl »), and implements the Iterator interface, allowing you to navigate through query results in a simpler manner:

foreach ($result as $row)
{
 var_dump($row);
}

For every iteration, $row will contain the next record as an array. This is equivalent to calling fetchRow() in a loop, like this:

while ($row = $result->fetchRow())
{
 var_dump($row);
}

In order to benefit from the Iterator implementation, you need to include the file Iterator.php from MDB2's directory by using the loadFile() method:

MDB2::loadFile('Iterator');

Then when you call query(), you pass the name of the Iterator class as a fourth parameter, like this:

$query = 'SELECT * FROM people';
$result = $mdb2->query($query, null, true, 'MDB2_BufferedIterator');

MDB2 comes with two Iterator classes:

  • MDB2_Iterator: This implements SPL's Iterator and is suitable to work with unbuffered results.
  • MDB2_BufferedIterator: This extends MDB2_Iterator and implements the SeekableIterator interface. When you work with buffered results (which is the default in MDB2), it's better to use MDB2_BufferedIterator, because it provides some more methods, like count() and rewind().

http://www.installationwiki.org/MDB2#Iterators »

Debugging

MDB2 allows you to keep a list of all queries executed in an instance, this way helping you debug your application. To enable the debugging, you need to set the debug option to a positive integer.

$mdb2->setOption('debug', 1);

Then you can get the collected debugging data at any point using:

$mdb2->getDebugOutput();

You can also set the option log_line_break, which specifies how the separate entries in the debug output will be delimited. The default delimiter is a line break \n.

Take a look at the following example that sets the debug option and the line separator, executes a few queries, and then draws an unordered list with the debug output.

$mdb2->setOption('debug', 1);
$mdb2->setOption('log_line_break', "\n\t");

$sql = 'SELECT * FROM people';
$result = $mdb2->query($sql);
$sql = 'SELECT * FROM people WHERE id = 1';
$result = $mdb2->query($sql);
$sql = 'SELECT name FROM people';
$result = $mdb2->query($sql);

$debug_array = explode("\n\t", trim($mdb2->getDebugOutput()));

echo '<ul><li>';
echo implode('</li><li>', $debug_array);
echo '</li></ul>';

This example will produce:

  • query(1): SELECT * FROM people
  • query(1): SELECT * FROM people WHERE id = 1
  • query(1): SELECT name FROM people

It's a good idea to reset the debug level to 0 when your application is in production, so that you don't have the overhead of storing all executed queries in the debug log.

http://www.installationwiki.org/MDB2#Extending_MDB2 »

Get the next auto_increment value

Some databases are not capable of the auto_increment function. MDB2 tries to maintain that abstraction with the following method.

$my_new_id = $mdb2->nextId('people');

This example shows getting the next increment id for the table people. You would use this when inserting a row into a table. Instead of leaving off the auto_increment column, you would use $mdb2->nextId('table_name') as the value for the id column every time you insert data.

It does this by actually creating another table that contains the increment number of a table.

http://www.installationwiki.org/MDB2#Sequences »

Transactions

If transactions are supported by your RDBMS, using them is very good practice to keep your data in a consistent state, should an error occur in the middle of the process of writing several pieces of data to one or more tables.

You begin by checking whether transactions are supported by your RDBMS and then you initiate a new transaction with a call to beginTransaction(). Then you start executing the different queries that comprise your transaction. After every query you can check the result and if you find it's a PEAR_Error, you can roll back (undo) the transaction and all previously executed queries within it. Otherwise you commit (finalize) the transaction. Before the calls to rollback() or commit(), you need to check if you really are in transaction, using the inTransaction() method.

if ($mdb2->supports('transactions'))
{
 $mdb2->beginTransaction();
}
$result = $mdb2->exec('DELETE FROM people WHERE id = 33');
if (PEAR::isError($result))
{
 if ($mdb2->inTransaction())
 {
 $mdb2->rollback();
 }
}
$result = $mdb2->exec('DELETE FROM people WHERE id = invalid something');
if (PEAR::isError($result))
{
 if ($mdb2->inTransaction())
 {
 $mdb2->rollback();
 }
} elseif ($mdb2->inTransaction())
{
 $mdb2->commit();
}

Note that if transactions are not supported by your RDBMS, MDB2 will not emulate this functionality, so it is your responsibility to keep the data in a consistent state.

http://www.installationwiki.org/MDB2#Transactions »

Page Comments (Click to edit)






[Click to add or edit comments])

Please prepend comments below including a date

Design by N.Design Studio, adapted by solidGone.org (version 1.0.0)
Have a nice day.