4

根据 Zend 用户指南,我的 ZF2 框架应用程序运行良好。但是现在我正在兜圈子,试图扩展应用程序,以便专辑的艺术家不再是字符串,而是我数据库中艺术家表的外键。

我已经创建了所有必要的模型、控制器、视图来创建、编辑和查看艺术家,它们也可以正常工作。但是如何将两者结合起来,以便我的专辑列表显示艺术家的名字?

我是否按照这里的建议使用保湿剂策略?如果是这样,我该如何实施?Zend\Stdlib\Hydrator\Strategy 手册没有告诉我在哪里注册 hydrator 策略。是的,有一个简短的实现代码:

$foo = new Foo();
$foo->setFoo("bar");
$foo->setBar("foo");

$hydrator = new ClassMethods();
$hydrator->addStrategy("foo", new Rot13Strategy());

但这会去哪里?在我的专辑控制器中?为什么每个人都说保湿剂“主要用于表格”?

或者说,保湿剂不是我想要的吗?我在寻求解决方案时不断遇到的另一件事是依赖注入。我再次找到了这种教程,但是在使用 A、B 和 C 类时,不告诉我所有这些代码片段的去向,这对理解这个概念没有多大帮助。

我认为我想做的事情很常见,而且我很惊讶我找不到任何现实世界的教程。经过数小时的研究,我确信我非常接近突破 - 但我再也看不到它了,需要推动。谢谢 :-)

4

1 回答 1

7

当您需要从对象/实体中获取数据或从对象/实体中获取数据时,可以使用水合器,这可能是在使用表单时,也可能是在从存储中保存或加载实体时。

我不会使用 Hydrator 来用相关对象填充您的对象(例如,将反对象对象添加到您的相册中)。我会把它留给你的服务/映射器。

这是我如何做的一个例子:

相册.php

<?php
class Album
{
     // .. properties / getters/setters etc ..

     public function setArtist(ArtistInterface $artist)
     {
         $this->artist = $artist;
     }

     public function getArtist()
     {
          return $this->artist;
     }
}

AlbumHydrator.php

这可能会有所不同,您将使用 getter/setter 或属性,查看基本 hydrators 以决定您要走哪条路线..

您的 Hydrator 将获取组装对象,并返回显示表单或保存到持久性等所需的数据。

<?php
class AlbumHydrator // extends Zend\Stdlib\Hydrator\ClassMethods
{
    public function extract($object)
    {
         return array(
             'artist_id'   => $object->getArtist()->getId(),
             'albumn_name' => $object->getAlbumName()
         )
    }

    // .. etc
}

专辑服务.php

<?php
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\ServiceManager; 

class AlbumService  implements ServiceManagerAwareInterface
{
    /**
     * Get an album, we'll also load any related objects here
     *
     * @param int
     */
    public function find($id)
    {
        $album = $this->_getAlbumMapper()->find($id);
        $artist = $this->_getArtistMapper()->findByAlbum($id);
        $album->setArtist($artist);

        return $album;
    }

     /**
     * Get the Mapper
     * 
     * @return  Application\Mappers\AlbumMapper
     */
    protected function _getAlbumMapper()
    {
        return $this->getServiceManager()
            ->get('AlbumMapper')
        ;
    }

    // ..
}

您将在 Service Manager 配置中设置您的服务,如下所示:

'AlbumService' => function($sm) {
    $mapper = $sm->get('AlbumMapper');
    $service = new Application\Service\AlbumService();
    $service->setAlbumMapper($mapper);

    return $service;
},

然后,您使用您的服务来创建您需要的对象图。您将为每个实体拥有单独的映射器,并且服务可以使用映射器来生成您需要的对象。

通常每个实体都有一个 Hydrator,映射器会使用它们为您填充对象。这取决于您的实现,您可能正在使用 TableGateway 或其他东西而不是映射器,这仍然可以正常工作。

现在是在控制器内部访问对象的示例

SomeController.php

public function albumAction()
{
    $id = (int) $this->params()->fromRoute('id', FALSE);
    if( ! $id) {
        // do something with errors etc ..
        return $this->redirect()->toRoute('default_route', array(
            'controller'    => 'index',
            'action'        => 'index'
        ));
    }
    $request = $this->getRequest();

    $album = $this->getServiceLocator()->get('AlbumService')->find($id);
    $artistName = $album->getArtist()->getName();

    return new ViewMdoel(
       'album'      => $ablum,
       'artistName' => $artistName
    );
}

使用集合时填充对象图有点棘手,但我倾向于使用延迟加载和虚拟代理进行这种设置,这基本上会延迟加载您需要的对象,直到您需要它们,检查这些:

http://phpmaster.com/intro-to-virtual-proxies-1/ http://phpmaster.com/intro-to-virtual-proxies-2/

于 2013-04-05T09:30:56.877 回答