首先,您似乎需要在概念上进行更多的飞跃。使用数据映射器模式,它有助于根据对象而不是数据库表进行思考。当我需要实现飞跃时,我发现这两篇文章很有帮助。
http://phpmaster.com/building-a-domain-model/
http://phpmaster.com/integrating-the-data-mappers/
话虽如此,ZF 1 有一些非常有用的工具可用于构建数据映射器/域模型。
ZF 1 中的约定是通过 Zend_Db_Table api 访问您正在使用的每个表。我发现的最简单的方法是只为每个表使用DbTable 资源。您也可以使用Zend_Db::factory
或new Zend_Db_Table('tableName')
或任何其他吸引您的方法。
此示例基于 mp3 歌曲曲目。
//in effect this is the database adapter for database table 'track', This is $tableGateway used later.
<?php
class Application_Model_DbTable_Track extends Zend_Db_Table_Abstract
{
//name of database table, required to be set if name of class does not match name of table
protected $_name = 'track';
//optional, column name of primary key
protected $_primary = 'id';
}
有几种方法可以将表附加到 Db 适配器和 Zend_Db_Table api,我只是发现这种方法实现起来很简单,而且它也使设置映射器变得简单。
映射器类是数据源和您的对象(域实体)之间的桥梁。在本例中,映射器与 Zend_Db_Table 的 api 交互。
要理解的一个非常重要的点:当使用扩展 Zend_Db_Table_Abstract 的类时,您可以使用 Zend_Db 组件的所有基本功能。(find(),fetchall(), fetchRow(), select() ...)
<?php
class Music_Model_Mapper_Track extends Model_Mapper_Abstract
{
//the mapper to access the songs artist object
protected $artistMapper;
//the mapper to access to songs album object
protected $albumMapper;
/**
* accepts instance of Zend_Db_Table_Abstract
*
* @param Zend_Db_Table_Abstract $tableGateway
*/
public function __construct(Zend_Db_Table_Abstract $tableGateway = null)
{
//at this point I tend to hardcode $tablegateway but I don't have to
$tableGateway = new Application_Model_DbTable_Track();
parent::__construct($tableGateway);
//parent sets the $tablegateway variable and provides an abstract requirement
//for createEntity(), which is the point of this class
}
/**
* Creates concrete object of Music_Model_Track
*
* @param object $row
* @return Music_Model_Track
*/
public function createEntity($row)
{
$data = array(
'id' => $row->id,
'filename' => $row->filename,
'format' => $row->format,
'genre' => $row->genre,
'hash' => $row->hash,
'path' => $row->path,
'playtime' => $row->playtime,
'title' => $row->title,
'track_number' => $row->track_number,
'album' => $row->album_id,//foriegn key
'artist' => $row->artist_id//foriegn key
);
//instantiate new entity object
return new Music_Model_Track($data);
}
/**
* findById() is proxy for find() method and returns
* an entity object.
*
* @param type $id
* @return object Model_Entity_Abstract
*/
public function findById($id)
{
//instantiate the Zend_Db_Select object
$select = $this->getGateway()->select();
$select->where('id = ?', $id);
//retrieve one database table row
$row = $this->getGateway()->fetchRow($select);
//create one entity object Music_Model_Track
$entity = $this->createEntity($row);
//return one entity object Music_Model_Track
return $entity;
}
//truncated
}
之前所做的一切都是为了明确构建以下对象:
<?php
class Music_Model_Track extends Model_Entity_Abstract
{
/**
* $id, __set, __get and toArray() are implemented in the parent
*/
protected $album;
protected $artist;
protected $filename;
protected $format;
protected $genre;
protected $hash;
protected $path;
protected $playtime;
protected $title;
protected $track_number;
//artist and album mappers
protected $albumMapper = null;
protected $artistMapper = null;
//these are the important accessors/mutators because they convert a foreign key
//in the database table to an entity object.
public function getAlbum()
{
//if the album object is already set, use it.
if(!is_null($this->album) && $this->album instanceof Music_Model_Album) {
return $this->album;
} else {
//else we make a new album object
if(!$this->albumMapper) {
$this->albumMapper = new Music_Model_Mapper_Album();
}
//This is the album object we get from the id in our reference array.
return $this->albumMapper->findById($this->getReferenceId('album'));
}
}
//same as above only with the artist object.
public function getArtist()
{
if(!is_null($this->artist) && $this->artist instanceof Music_Model_Artist) {
return $this->artist;
} else {
if(!$this->artistMapper) {
$this->artistMapper = new Music_Model_Mapper_Artist();
}
return $this->artistMapper->findById($this->getReferenceId('artist'));
}
}
//the setters record the foriegn keys recorded in the table row to an array,
//this allows the album and artist objects to be loaded only when needed.
public function setAlbum($album)
{
$this->setReferenceId('album', $album);
return $this;
}
public function setArtist($artist)
{
$this->setReferenceId('artist', $artist);
return $this;
}
//standard setter and getters truncated...
}
so when using the track object you would get album or artist info like:
//this would be used in a controller most likely.
$mapper = new Music_Model_Mapper_Track();
$track = $mapper->findById('1');
//all of the information contained in the album or artist object is
//available to the track object.
//echo album title, year or artist. This album object also contains the artist object
//so the artist object would be available in two ways.
echo $track->album->title; //or
echo $track->artist->name;
echo $track->album->artist->name;
echo $track->getAlbum()->getArtist()->getName();
所以你真正需要决定的是你想如何构建你的应用程序。我认为显而易见的可能不是您希望实施的选项。您的问题的很多答案都取决于这些资源的确切使用方式。
我希望这至少对您有所帮助。