CHAPTER 13 ■ DATABASE PATTERNS
In fact, since the Space objects are effectively subordinate to Venue objects, it may be possible to
factor the SpaceMapper class into VenueMapper. For the sake of these exercises, I’m going to keep them
separate.
As you can see, the classes present common operations for saving and loading data. The base class
stores common functionality, delegating responsibility for handling object-specific operations to its
children. Typically, these operations include actual object generation and constructing queries for
database operations.
The base class often performs housekeeping before or after an operation, which is why Template
Method is used for explicit delegation (calls from concrete methods like insert() to abstract ones like
doInsert(), etc.). Implementation determines which of the base class methods are made concrete in this
way, as you will see later in the chapter.
Here is a simplified version of a Mapper base class:
namespace woo\mapper;
//...
abstract class Mapper {
protected static $PDO;
function __construct() {
if (! isset(self::$PDO) ) {
$dsn = \woo\base\ApplicationRegistry::getDSN( );
if ( is_null( $dsn ) ) {
throw new \woo\base\AppException( "No DSN" );
}
self::$PDO = new \PDO( $dsn );
self::$PDO->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
}
}
function find( $id ) {
$this->selectStmt()->execute( array( $id ) );
$array = $this->selectStmt()->fetch( );
$this->selectStmt()->closeCursor( );
if (! is_array( $array ) ) { return null; }
if (! isset( $array['id'] ) ) { return null; }
$object = $this->createObject( $array );
return $object;
}
function createObject( $array ) {
$obj = $this->doCreateObject( $array );
return $obj;
}
function insert( \woo\domain\DomainObject $obj ) {
$this->doInsert( $obj );
}
abstract function update( \woo\domain\DomainObject $object );
protected abstract function doCreateObject( array $array );
protected abstract function doInsert( \woo\domain\DomainObject $object );
protected abstract function selectStmt();
}