短い答えはイエスです!
データベースから何かを取得する必要がある場合は、ほとんどどこかでマッパーを使用する必要があります。これは、理想的には、ドメイン モデルがデータベースをまったく認識しないか、マッパーが実際に存在することを認識しないようにする必要があるためです。
ドメイン モデルとマッパーを使用およびアクセスするための多くの戦略とパターンがあると確信しています。また、これらのリソースをどのように活用するのが最善かについて、誰もが異なる意見を持っていると確信しています. 肝心なのは、使用方法を知っているものを使用する必要があるということです。後で詳しく知ったときに、いつでもリファクタリングできます。
例として、ベース マッパーとベース エンティティ (ドメイン) モデルを含めます。
<?php
/**
* Base mapper model to build concrete data mappers around.
* Includes identity map functionallity.
*/
abstract class My_Application_Model_Mapper
{
protected $_tableGateway = NULL;
protected $_map = array();
/**
* Will accept a DbTable model passed or will instantiate
* a Zend_Db_Table_Abstract object from table name.
*
* @param Zend_Db_Table_Abstract $tableGateway
*/
public function __construct(Zend_Db_Table_Abstract $tableGateway = NULL) {
if (is_null($tableGateway)) {
$this->_tableGateway = new Zend_Db_Table($this->_tableName);
} else {
$this->_tableGateway = $tableGateway;
}
}
/**
* @return Zend_Db_Table_Abstract
*/
protected function _getGateway() {
return $this->_tableGateway;
}
/**
* @param string $id
* @param object $entity
*/
protected function _setMap($id, $entity) {
$this->_map[$id] = $entity;
}
/**
* @param string $id
* @return string
*/
protected function _getMap($id) {
if (array_key_exists($id, $this->_map)) {
return $this->_map[$id];
}
}
/**
* findByColumn() returns an array of rows selected
* by column name and column value.
* Optional orderBy value.
*
* @param string $column
* @param string $value
* @param string $order
* @return array
*/
public function findByColumn($column, $value, $order = NULL) {
$select = $this->_getGateway()->select();
$select->where("$column = ?", $value);
if (!is_null($order)) {
$select->order($order);
}
$result = $this->_getGateway()->fetchAll($select);
$entities = array();
foreach ($result as $row) {
$entity = $this->createEntity($row);
$this->_setMap($row->id, $entity);
$entities[] = $entity;
}
return $entities;
}
/**
* findById() is proxy for find() method and returns
* an entity object. Utilizes fetchRow() because it returns row object
* instead of primary key as find() does.
* @param string $id
* @return object
*/
public function findById($id) {
//return identity map entry if present
if ($this->_getMap($id)) {
return $this->_getMap($id);
}
$select = $this->_getGateway()->select();
$select->where('id = ?', $id);
//result set, fetchRow returns a single row object
$row = $this->_getGateway()->fetchRow($select);
//create object
$entity = $this->createEntity($row);
//assign object to odentity map
$this->_setMap($row->id, $entity);
return $entity;
}
/**
* findAll() is a proxy for the fetchAll() method and returns
* an array of entity objects.
* Optional Order parameter. Pass order as string ie. 'id ASC'
* @param string $order
* @return array
*/
public function findAll($order = NULL) {
$select = $this->_getGateway()->select();
if (!is_null($order)) {
$select->order($order);
}
$rowset = $this->_getGateway()->fetchAll($select);
$entities = array();
foreach ($rowset as $row) {
$entity = $this->createEntity($row);
$this->_setMap($row->id, $entity);
$entities[] = $entity;
}
return $entities;
}
/**
* Abstract method to be implemented by concrete mappers.
*/
abstract protected function createEntity($row);
}
ベース ドメイン オブジェクトは次のとおりです。
<?php
/**
* Base domain object
* includes lazy loading of foreign key objects.
*/
abstract class My_Application_Model_Entity_Abstract
{
protected $_references = array();
/**
* Accepts an array to instantiate the object, else use
* __set() when creating objects
* @param array $options
*/
public function __construct(array $options = NULL) {
if (is_array($options)) {
$this->setOptions($options);
}
}
/**
* @param array $options
* @return \My_Application_Model_Entity_Abstract
*/
public function setOptions(array $options) {
$methods = get_class_methods($this);
foreach ($options as $key => $value) {
$method = 'set' . ucfirst($key);
if (in_array($method, $methods)) {
$this->$method($value);
}
}
return $this;
}
/**
* Map the setting of non-existing fields to a mutator when
* possible, otherwise use the matching field
*/
public function __set($name, $value) {
$property = '_' . strtolower($name);
if (!property_exists($this, $property)) {
throw new \InvalidArgumentException("Setting the property '$property'
is not valid for this entity");
}
$mutator = 'set' . ucfirst(strtolower($name));
if (method_exists($this, $mutator) && is_callable(array($this, $mutator))) {
$this->$mutator($value);
} else {
$this->$property = $value;
}
return $this;
}
/**
* Map the getting of non-existing properties to an accessor when
* possible, otherwise use the matching field
*/
public function __get($name) {
$property = '_' . strtolower($name);
if (!property_exists($this, $property)) {
throw new \InvalidArgumentException(
"Getting the property '$property' is not valid for this entity");
}
$accessor = 'get' . ucfirst(strtolower($name));
return (method_exists($this, $accessor) && is_callable(array(
$this, $accessor))) ? $this->$accessor() : $this->$property;
}
/**
* Get the entity fields.
*/
public function toArray() {
//TODO
}
/**
* set and get for _references array, allows the potential to lazy load
* foreign objects.
*/
public function setReferenceId($name, $id) {
$this->_references[$name] = $id;
}
public function getReferenceId($name) {
if (isset($this->_references[$name])) {
return $this->_references[$name];
}
}
}
これらの概念とテクニックを理解するために、多くのチュートリアルと書籍を参照しました。
これらのオブジェクトの使用は必要に応じて行われます。DB からオブジェクトをプルする必要がある場合はマッパーを呼び出します。フォーム データ (またはその他のデータ) を使用してオブジェクトを構築する必要がある場合は、オブジェクトを直接呼び出すことができます。
これがいくらか役立つことを願っています。幸運を!