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

时间:2013-08-21 13:51:04

标签: php sql-server zend-framework2

我正在http://framework.zend.com/manual/2.0/en/user-guide/database-and-models.html上关注该教程,并且我已经设置了Module::getServiceConfig()和我的AlbumTable课程。

现在说我需要执行存储过程来获取结果集...而不是标准SELECT。我仍然希望结果集是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模型兼容的结果。
^并不意味着态度,只是试图拯救每个人建议我不需要使用存储过程。

1 个答案:

答案 0 :(得分:3)

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

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

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()方法。当我在smalldatetime方法中将数据库中的\DateTime值转换为exchangeArray()对象时,我意识到这一点......它没有被调用。

对此的解决方法是使用ArraySerializable保湿器。所以我已经更新了上面的代码来证明这一点。

如果您希望保湿器使用您的孵化器(例如setArtist()setTitle()),您可以使用ClassMethods保湿器。

如果您的属性是公开的(或者您正在使用魔法__set()方法),则可以使用ObjectProperty水分器,它只会将值分配给您的属性。