如何在ZF2中执行手动编写的查询或存储过程


How to execute a manually-written query or stored procedure in ZF2

我在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());
}

问题是返回的$resultArrayObject的集合…而不是Album模型的集合。那么,我如何执行存储过程,但仍然可以根据我在Module::getServiceConfig()中设置的内容获得结果呢?

请不要问我的存储过程在做什么。。。这与这个问题无关。重点是,它返回与Album模型兼容的结果
^这并不是一种态度,只是为了节省每个人建议我不需要使用存储过程的时间

正如@Sam在问题注释中建议的那样,似乎没有办法在TableGateway对象上执行本机SQL查询,因此您必须手动对数据对象进行水合。

在查看了Zend在HydratingResultSet上的文档后,以下是我提出的解决方案:

namespace Album'Table;
use Zend'Db'TableGateway'TableGateway;
use Zend'Db'ResultSet'HydratingResultSet;
use Zend'Stdlib'Hydrator;
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 Hydrator'ArraySerializable(),
                new 'Album'Model'Album()
            );
            $result->initialize($dataSource);
        }
        return $result;
    }
}

更新:

我真的不知道ReflectionHydrator发生了什么。它通过反射填充我的对象,而不是调用我的exchangeArray()方法。当我用exchangeArray()方法将数据库中的smalldatetime值转换为'DateTime对象时,我意识到了这一点。。。它没有接到电话。

解决方法是使用ArraySerializable水合器。因此,我更新了上面的代码来演示这一点。

如果你想让水合器使用你的设定器(如setArtist()setTitle()),你可以使用ClassMethods水合器。

如果你的属性是公共的(或者如果你使用的是神奇的__set()方法),你可以使用ObjectProperty水合器,它只会为你的属性分配值。