2013-04-05 25 views
4

根据Zend用户指南,我的ZF2框架应用程序可以正常工作。但现在我正在试图扩展应用程序,以便专辑的艺术家不再是字符串,而是我的数据库中艺术家表的外键。如何扩展ZF2框架应用程序 - 使用外键的实体

我创建了所有必要的模型,控制器,视图来创建,编辑和查看艺术家,这也很好。但是我怎么把两者结合起来才能让我的专辑列表显示艺术家的名字?

我使用水化器策略as suggested here?如果是这样,我该如何执行它? Zend \ Stdlib \ Hydrator \ Strategy手册不会告诉我在哪里注册hydrator策略。是的,有一个简短的实施代码:

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

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

但是,这是去哪里?在我的AlbumController?为什么每个人都说补水剂“主要用于形式”?

或者不是我正在寻找的水合物?我在追求解决方案时遇到的另一件事是依赖注入。我再一次发现了这个kind of tutorial,但是在使用A,B和C类时,并没有告诉我所有这些代码片段在哪里移动,这对理解概念并没有多大的帮助。

我觉得我想要做的事很常见,我错开了我找不到任何真实世界的教程。经过数小时的研究,我确信我非常接近突破 - 但我再也看不到它了,需要推动。谢谢:-)

回答

7

当您需要将数据导入或导出对象/实体(可以是使用表单时,或者也可以在从存储器中保存或加载实体时)时使用水化器。

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

下面是一个例子,我怎么会做它:

Album.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将采取组装的对象TS,并给回你就需要或者表现出的形式,或者保存到持久性等

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

    // .. etc 
} 

AlbumService.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') 
     ; 
    } 

    // .. 
} 

你会设置你的服务在服务管理器中的数据像这样的配置:

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

    return $service; 
}, 

然后,你使用你的服务来创建你需要的对象图。您可以为每个实体分别创建映射器,这些服务可以使用映射器来生成所需的对象。

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

现在的访问时,控制器

里面你的对象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/

+0

非常感谢!因此,您使用该服务来组装包含艺术家对象的相册对象,并从该组合对象中提取用于保存到存储的artist_id的水合器,是否正确? – Streamflyer 2013-04-05 10:34:13

+0

我该如何使服务对ServiceLocator可见?我在'class AlbumService'中包装了代码,尝试了在其他服务类中看到的“实现ServiceManagerAwareInterface”,但是我的ServiceLocator未能找到它。 – Streamflyer 2013-04-05 10:37:07

+0

稍微更新.. – Andrew 2013-04-05 11:09:34