我在http://framework.zend.com/manual/2.0/en/user-guide/database-and-models.html,并且我已经设置了我的Module::getServiceConfig()
和AlbumTable
类,如图所示。
现在假设我需要执行一个存储过程来获得结果集。。。而不是标准的CCD_ 3。我仍然希望结果集是Album
模型的集合。如何做到这一点?
下面是我尝试过的一个例子:
AlbumTable.php:
public function findByArtist($artist) {
$adapter = $this->tableGateway->getAdapter();
$result = $adapter->query(
"EXEC spGetAlbums @artist = :artist",
array(':artist' => $artist)
);
var_dump($result->current());
}
问题是返回的$result
是ArrayObject
的集合…而不是Album
模型的集合。那么,我如何执行存储过程,但仍然可以根据我在Module::getServiceConfig()
中设置的内容获得结果呢?
请不要问我的存储过程在做什么。。。这与这个问题无关。重点是,它返回与Album
模型兼容的结果
^这并不是一种态度,只是为了节省每个人建议我不需要使用存储过程的时间
正如@Sam在问题注释中建议的那样,似乎没有办法在TableGateway
对象上执行本机SQL查询,因此您必须手动对数据对象进行水合。
在查看了Zend在HydratingResultSet
上的文档后,以下是我提出的解决方案:
namespace AlbumTable;
use ZendDbTableGatewayTableGateway;
use ZendDbResultSetHydratingResultSet;
use ZendStdlibHydrator;
class Album {
protected $tableGateway;
public function __construct(TableGateway $tableGateway) {
$this->tableGateway = $tableGateway;
}
public function findByArtist($artist) {
$adapter = $this->tableGateway->getAdapter();
$result = $adapter->query(
"EXEC spGetAlbums @artist = :artist",
array(':artist' => $artist)
);
$dataSource = $result->getDataSource();
if ($dataSource instanceof Iterator) {
$result = new HydratingResultSet(
new HydratorArraySerializable(),
new AlbumModelAlbum()
);
$result->initialize($dataSource);
}
return $result;
}
}
更新:
我真的不知道ReflectionHydrator
发生了什么。它通过反射填充我的对象,而不是调用我的exchangeArray()
方法。当我用exchangeArray()
方法将数据库中的smalldatetime
值转换为DateTime
对象时,我意识到了这一点。。。它没有接到电话。
解决方法是使用ArraySerializable
水合器。因此,我更新了上面的代码来演示这一点。
如果你想让水合器使用你的设定器(如setArtist()
和setTitle()
),你可以使用ClassMethods
水合器。
如果你的属性是公共的(或者如果你使用的是神奇的__set()
方法),你可以使用ObjectProperty
水合器,它只会为你的属性分配值。