eZ publish Enterprise Component: Database, Design ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Introduction ============ Purpose of the Database component --------------------------------- The Database component provides an interface for: - Database API abstraction - SQL abstraction It lets the user interact with different DBMSs using a common API. Such differences between SQL dialects may include differences in OFFSET and LIMIT clauses, left/right joins, temporary tables and strings quoting. These are also handled transparently for the user. Current implementation ---------------------- The current implementation mostly supports database API abstraction (built on-top of PDO classes (see http://php.net/PDO); SQL abstraction is not implemented yet. Requirements ============ The component should provide simple but extensible API. It must be possible for application to register support for other DBMSs. Design ====== The component consists of the following main classes: - ezcDbHandler - ezcDbFactory - ezcDbInstance ezcDbHandler --------------------- Provides the common interface for database operations, such as connecting, running queries, etc. This interface is derived by concrete *handlers*, e.g. MySQL handler or PostgreSQL handler. ezcDbFactory ------------ Implements a Factory design pattern. It contains list of known handlers and is used to create instances of them. It is possible to register user-specified handlers with the factory. ezcDbInstance ------------- Most applications need only one database connection. It is convenient for such applications to create a connection once, and then make it globally accessible and use it anywhere within the application. Even if an application requires two or more database connections, it's handy not to pass them to every method that needs them, but to access them easily from any place. To satisfy these requirements, the ezcDbInstance class is suggested. It's capable of saving one or more database connections, with the ability to assign them names (identifiers). These names can then be used to refer to the connection. How to use ========== Usually the component is used in the following way: - User creates an instance of a handler with ezcFactory class. - (optionally) User saves the instance to singleton. - He/she does misc. database operations on the instance. A more sophisticated scenario includes defining a custom handler and registering it with the factory. If the user needs to work with several database connections simultaneously, he/she creates several handler instances, then saves them to ezcDbInstance giving them short name for sake of convenience. Examples ======== Let's look at some examples to make everything clear. Example 1: The simplest case ---------------------------- :: $dbparams = array( 'dbname' => 'circus', 'user' => 'monty', 'pass' => 'python' ); $db = ezcDbFactory::create( 'mysql', $dbparams ); $rslt = $db->query( 'SELECT * FROM tbl' ); In the example above we create an instance of MySQL handler and run a query on it. Example 2: Using singleton -------------------------- :: $db = ezcDbFactory::create( 'mysql', $dbparams ); ezcDbInstance::set( $db ); unset( $db ); # ... $db = ezcDbInstance::get(); $rslt = $db->query( 'SELECT * FROM tbl' ); In this case, we use ezcDbInstance to save the instance we have created. It can be easily accessed from any place with just one one call to ezcDbInstance::get(). The class ezcDbInstance behaves much like singleton in this case. Example 3: Multiple connections ------------------------------- :: $db1 = ezcDbFactory::create( 'mysql', $dbparams1 ); $db2 = ezcDbFactory::create( 'mysql', $dbparams2 ); ezcDbInstance::set( $db1, 'db1' ); ezcDbInstance::set( $db2, 'db2' ); unset( $db1, $db2 ); # ... $db1 = ezcDbInstance::get( 'db1' ); $db2 = ezcDbInstance::get( 'db2' ); Here we have two different MySQL connections. We save them to ezcDbInstance, giving them names 'db1' and 'db2', accordingly. The connections are then referred to in call to ezcDbInstance::get() by these names. Example 4: Custom handler ------------------------- :: class MyOciDbHandler extends ezcDbHandler { ... } # ... ezcDbFactory::addImplementation( 'myoci', 'MyOciDbHandler' ); $db = ezcDbFactory::create( 'myoci', $dbparams ); $rslt = $db->query( 'SELECT count(*) AS cnt FROM user_tables' ); In this example we define our own handler for communicating with Oracle. The handler is then registered with the factory by calling method ezcDbFactory::addImplementation(). Then we can use the handler in the usual way, as if it was a standard implementation. See also ======== - For more information about PDO please visit the following page: http://php.net/PDO - See real examples (with errors handling) in test.php file bundled with the Database package.