PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1

CHAPTER 13 ■ DATABASE PATTERNS


The constructor method uses an ApplicationRegistry to get a DSN for use with the PDO extension.
A standalone singleton or a request-scoped registry really come into their own for classes like this. There
isn’t always a sensible path from the control layer to a Mapper along which data can be passed. Another
way of managing mapper creation would be to hand it off to the Registry class itself. Rather than
instantiate it, the mapper would expect to be provided with a PDO object as a constructor argument.


namespace woo\mapper;
//...
abstract class Mapper {
protected $PDO;
function __construct( \PDO $pdo ) {
$this->pdo = $pdo;
}
}


Client code would acquire a new VenueMapper from Registry using \woo\base\Request
Registry::getVenueMapper( ). This would instantiate a mapper, generating the PDO object too. For
subsequent requests, the method would return the cached mapper. The trade-off here is that you make
Registry much more knowledgeable about your system, but your mappers remain ignorant of global
configuration data.
The insert() method does nothing but delegate to doInsert(). This would be something that I
would factor out in favor of an abstract insert() method were it not for the fact that I know that the
implementation will be useful here in due course.
find() is responsible for invoking a prepared statement (provided by an implementing child class)
and acquiring row data. It finishes up by calling createObject(). The details of converting an array to an
object will vary from case to case, of course, so the details are handled by the abstract doCreateObject()
method. Once again, createObject() seems to do nothing but delegate to the child implementation, and
once again, I’ll soon add the housekeeping that makes this use of the Template Method pattern worth
the trouble.
Child classes will also implement custom methods for finding data according to specific criteria (I
will want to locate Space objects that belong to Venue objects, for example).
You can take a look at the process from the child’s perspective here:


namespace woo\mapper;
//...


class VenueMapper extends Mapper {
function construct() {
parent::
construct();
$this->selectStmt = self::$PDO->prepare(
"SELECT * FROM venue WHERE id=?");
$this->updateStmt = self::$PDO->prepare(
"update venue set name=?, id=? where id=?");
$this->insertStmt = self::$PDO->prepare(
"insert into venue ( name )
values(? )");
}


function getCollection( array $raw ) {
return new SpaceCollection( $raw, $this );
}
protected function doCreateObject( array $array ) {
$obj = new \woo\domain\Venue( $array['id'] );
$obj->setname( $array['name'] );

Free download pdf