Php 如何使用基于ZfcBase DbMapper的模型在敏捷性驱动的应用程序中构建嵌套响应?
我正在开发一个RESTful web应用程序——由驱动并基于。对于模型层,我使用了。该模型基本上由两个实体组成:Php 如何使用基于ZfcBase DbMapper的模型在敏捷性驱动的应用程序中构建嵌套响应?,php,zend-framework2,one-to-many,datamapper,laminas-api-tools,Php,Zend Framework2,One To Many,Datamapper,Laminas Api Tools,我正在开发一个RESTful web应用程序——由驱动并基于。对于模型层,我使用了。该模型基本上由两个实体组成:Project和Image(1:n),目前的实现方式如下: ProjectCollection extends Paginator ProjectEntity ProjectMapper extends AbstractDbMapper ProjectService implements ServiceManagerAwareInterface ProjectServiceFactor
Project
和Image
(1:n
),目前的实现方式如下:
ProjectCollection extends Paginator
ProjectEntity
ProjectMapper extends AbstractDbMapper
ProjectService implements ServiceManagerAwareInterface
ProjectServiceFactory implements FactoryInterface
use ZF\Hal\Collection
...
$images = new Collection($arrayOfImages);
$project['images'] = $images;
图像的结构相同
当请求资源(/projects[/:id]
)时,响应的项目实体应包含其图像实体的列表
那么,这个1:n
结构应该如何实现呢?
子问题:
[DbMapper
]是否提供了一些“魔法”来“自动”检索这样的树结构,而无需编写JOIN
s(或使用ORM)
[Apigility
]是否为构建嵌套响应提供了一些“魔力”
编辑
我目前得到的输出是:
/projects/:id
{
"id": "1",
"title": "...",
...
"_embedded": {
"images": [
{
"id": "1",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/1"
}
}
},
{
"id": "2",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/2"
}
}
},
{
"id": "3",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/3"
}
}
}
]
},
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
}
{
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects?page=1"
},
"first": {
"href": "http://myproject-api.misc.loc/projects"
},
"last": {
"href": "http://myproject-api.misc.loc/projects?page=24"
},
"next": {
"href": "http://myproject-api.misc.loc/projects?page=2"
}
},
"_embedded": {
"projects": [
{
"id": "1",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
},
{
"id": "2",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/2"
}
}
},
{
"id": "3",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/3"
}
}
}
]
},
"page_count": 24,
"page_size": 3,
"total_items": 72
}
public function findAll() {
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
return array(
...
'zf-hal' => array(
'metadata_map' => array(
...
'Portfolio\\V2\\Rest\\Project\\ProjectEntity' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'hydrator' => 'Portfolio\\V2\\Rest\\Project\\ProjectHydrator',
),
'Portfolio\\V2\\Rest\\Project\\ProjectCollection' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'is_collection' => true,
),
...
),
),
);
class Module implements ApigilityProviderInterface {
...
public function getHydratorConfig() {
return array(
'factories' => array(
// V2
'Portfolio\\V2\\Rest\\Project\\ProjectHydrator' => function(ServiceManager $serviceManager) {
$projectHydrator = new ProjectHydrator();
$projectHydrator->setImageService($serviceManager->getServiceLocator()->get('Portfolio\V2\Rest\ImageService'));
return $projectHydrator;
}
),
);
}
...
}
namespace Portfolio\V2\Rest\Project;
use Zend\Stdlib\Hydrator\ClassMethods;
use Portfolio\V2\Rest\Image\ImageService;
class ProjectHydrator extends ClassMethods {
/**
* @var ImageService
*/
protected $imageService;
/**
* @return ImageService the $imageService
*/
public function getImageService() {
return $this->imageService;
}
/**
* @param ImageService $imageService
*/
public function setImageService(ImageService $imageService) {
$this->imageService = $imageService;
return $this;
}
/*
* Doesn't need to be implemented:
* the ClassMethods#hydrate(...) handle the $data already as wished.
*/
/*
public function hydrate(array $data, $object) {
$object = parent::hydrate($data, $object);
if ($object->getId() !== null) {
$images = $this->imageService->getImagesForProject($object->getId());
$object->setImages($images);
}
return $object;
}
*/
/**
* @see \Zend\Stdlib\Hydrator\ClassMethods::extract()
*/
public function extract($object) {
$array = parent::extract($object);
if ($array['id'] !== null) {
$images = $this->imageService->getImagesForProject($array['id']);
$array['images'] = $images;
}
return $array;
}
}
namespace Portfolio\V2\Rest\Project;
use Zend\ServiceManager\ServiceLocatorInterface;
class ProjectMapperFactory {
public function __invoke(ServiceLocatorInterface $serviceManager) {
$mapper = new ProjectMapper();
$mapper->setDbAdapter($serviceManager->get('PortfolioDbAdapter_V2'));
$mapper->setEntityPrototype($serviceManager->get('Portfolio\V2\Rest\Project\ProjectEntity'));
$projectHydrator = $serviceManager->get('HydratorManager')->get('Portfolio\\V2\\Rest\\Project\\ProjectHydrator');
$mapper->setHydrator($projectHydrator);
return $mapper;
}
}
namespace Portfolio\V2\Rest\Project;
use ZfcBase\Mapper\AbstractDbMapper;
use Zend\Paginator\Adapter\DbSelect;
use Zend\Db\ResultSet\HydratingResultSet;
class ProjectMapper extends AbstractDbMapper {
...
/**
* Provides a collection of all the available projects.
*
* @return \Portfolio\V2\Rest\Project\ProjectCollection
*/
public function findAll() {
$resultSetPrototype = new HydratingResultSet(
$this->getHydrator(),
$this->getEntityPrototype()
);
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter, $resultSetPrototype);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
/**
* Provides a project by ID.
*
* @param int $id
* @return \Portfolio\V2\Rest\Project\ProjectEntity
*/
public function findById($id) {
$select = $this->getSelect();
$select->where(array(
'id' => $id,
));
$entity = $this->select($select)->current();
return $entity;
}
...
}
因此,它适用于单个对象。但不适用于集合,其中单个项目包括更多集合:
/projects
{
"id": "1",
"title": "...",
...
"_embedded": {
"images": [
{
"id": "1",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/1"
}
}
},
{
"id": "2",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/2"
}
}
},
{
"id": "3",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/3"
}
}
}
]
},
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
}
{
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects?page=1"
},
"first": {
"href": "http://myproject-api.misc.loc/projects"
},
"last": {
"href": "http://myproject-api.misc.loc/projects?page=24"
},
"next": {
"href": "http://myproject-api.misc.loc/projects?page=2"
}
},
"_embedded": {
"projects": [
{
"id": "1",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
},
{
"id": "2",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/2"
}
}
},
{
"id": "3",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/3"
}
}
}
]
},
"page_count": 24,
"page_size": 3,
"total_items": 72
}
public function findAll() {
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
return array(
...
'zf-hal' => array(
'metadata_map' => array(
...
'Portfolio\\V2\\Rest\\Project\\ProjectEntity' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'hydrator' => 'Portfolio\\V2\\Rest\\Project\\ProjectHydrator',
),
'Portfolio\\V2\\Rest\\Project\\ProjectCollection' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'is_collection' => true,
),
...
),
),
);
class Module implements ApigilityProviderInterface {
...
public function getHydratorConfig() {
return array(
'factories' => array(
// V2
'Portfolio\\V2\\Rest\\Project\\ProjectHydrator' => function(ServiceManager $serviceManager) {
$projectHydrator = new ProjectHydrator();
$projectHydrator->setImageService($serviceManager->getServiceLocator()->get('Portfolio\V2\Rest\ImageService'));
return $projectHydrator;
}
),
);
}
...
}
namespace Portfolio\V2\Rest\Project;
use Zend\Stdlib\Hydrator\ClassMethods;
use Portfolio\V2\Rest\Image\ImageService;
class ProjectHydrator extends ClassMethods {
/**
* @var ImageService
*/
protected $imageService;
/**
* @return ImageService the $imageService
*/
public function getImageService() {
return $this->imageService;
}
/**
* @param ImageService $imageService
*/
public function setImageService(ImageService $imageService) {
$this->imageService = $imageService;
return $this;
}
/*
* Doesn't need to be implemented:
* the ClassMethods#hydrate(...) handle the $data already as wished.
*/
/*
public function hydrate(array $data, $object) {
$object = parent::hydrate($data, $object);
if ($object->getId() !== null) {
$images = $this->imageService->getImagesForProject($object->getId());
$object->setImages($images);
}
return $object;
}
*/
/**
* @see \Zend\Stdlib\Hydrator\ClassMethods::extract()
*/
public function extract($object) {
$array = parent::extract($object);
if ($array['id'] !== null) {
$images = $this->imageService->getImagesForProject($array['id']);
$array['images'] = $images;
}
return $array;
}
}
namespace Portfolio\V2\Rest\Project;
use Zend\ServiceManager\ServiceLocatorInterface;
class ProjectMapperFactory {
public function __invoke(ServiceLocatorInterface $serviceManager) {
$mapper = new ProjectMapper();
$mapper->setDbAdapter($serviceManager->get('PortfolioDbAdapter_V2'));
$mapper->setEntityPrototype($serviceManager->get('Portfolio\V2\Rest\Project\ProjectEntity'));
$projectHydrator = $serviceManager->get('HydratorManager')->get('Portfolio\\V2\\Rest\\Project\\ProjectHydrator');
$mapper->setHydrator($projectHydrator);
return $mapper;
}
}
namespace Portfolio\V2\Rest\Project;
use ZfcBase\Mapper\AbstractDbMapper;
use Zend\Paginator\Adapter\DbSelect;
use Zend\Db\ResultSet\HydratingResultSet;
class ProjectMapper extends AbstractDbMapper {
...
/**
* Provides a collection of all the available projects.
*
* @return \Portfolio\V2\Rest\Project\ProjectCollection
*/
public function findAll() {
$resultSetPrototype = new HydratingResultSet(
$this->getHydrator(),
$this->getEntityPrototype()
);
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter, $resultSetPrototype);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
/**
* Provides a project by ID.
*
* @param int $id
* @return \Portfolio\V2\Rest\Project\ProjectEntity
*/
public function findById($id) {
$select = $this->getSelect();
$select->where(array(
'id' => $id,
));
$entity = $this->select($select)->current();
return $entity;
}
...
}
编辑为:
public function getProjects() {
$projects = $this->getMapper()->findAll();
foreach ($projects as $key => $project) {
$images = $this->getImageService()->getImagesForProject($project['id']);
$projects[$key]['images'] = $images;
}
return $projects;
}
public function findAll() {
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter);
// @todo Replace the constants with data from the config and request.
$projects = $paginatorAdapter->getItems(0, 2);
$projects = $projects->toArray();
return $projects;
}
以及项目映射器#findAll()
{
"id": "1",
"title": "...",
...
"_embedded": {
"images": [
{
"id": "1",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/1"
}
}
},
{
"id": "2",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/2"
}
}
},
{
"id": "3",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/3"
}
}
}
]
},
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
}
{
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects?page=1"
},
"first": {
"href": "http://myproject-api.misc.loc/projects"
},
"last": {
"href": "http://myproject-api.misc.loc/projects?page=24"
},
"next": {
"href": "http://myproject-api.misc.loc/projects?page=2"
}
},
"_embedded": {
"projects": [
{
"id": "1",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
},
{
"id": "2",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/2"
}
}
},
{
"id": "3",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/3"
}
}
}
]
},
"page_count": 24,
"page_size": 3,
"total_items": 72
}
public function findAll() {
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
return array(
...
'zf-hal' => array(
'metadata_map' => array(
...
'Portfolio\\V2\\Rest\\Project\\ProjectEntity' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'hydrator' => 'Portfolio\\V2\\Rest\\Project\\ProjectHydrator',
),
'Portfolio\\V2\\Rest\\Project\\ProjectCollection' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'is_collection' => true,
),
...
),
),
);
class Module implements ApigilityProviderInterface {
...
public function getHydratorConfig() {
return array(
'factories' => array(
// V2
'Portfolio\\V2\\Rest\\Project\\ProjectHydrator' => function(ServiceManager $serviceManager) {
$projectHydrator = new ProjectHydrator();
$projectHydrator->setImageService($serviceManager->getServiceLocator()->get('Portfolio\V2\Rest\ImageService'));
return $projectHydrator;
}
),
);
}
...
}
namespace Portfolio\V2\Rest\Project;
use Zend\Stdlib\Hydrator\ClassMethods;
use Portfolio\V2\Rest\Image\ImageService;
class ProjectHydrator extends ClassMethods {
/**
* @var ImageService
*/
protected $imageService;
/**
* @return ImageService the $imageService
*/
public function getImageService() {
return $this->imageService;
}
/**
* @param ImageService $imageService
*/
public function setImageService(ImageService $imageService) {
$this->imageService = $imageService;
return $this;
}
/*
* Doesn't need to be implemented:
* the ClassMethods#hydrate(...) handle the $data already as wished.
*/
/*
public function hydrate(array $data, $object) {
$object = parent::hydrate($data, $object);
if ($object->getId() !== null) {
$images = $this->imageService->getImagesForProject($object->getId());
$object->setImages($images);
}
return $object;
}
*/
/**
* @see \Zend\Stdlib\Hydrator\ClassMethods::extract()
*/
public function extract($object) {
$array = parent::extract($object);
if ($array['id'] !== null) {
$images = $this->imageService->getImagesForProject($array['id']);
$array['images'] = $images;
}
return $array;
}
}
namespace Portfolio\V2\Rest\Project;
use Zend\ServiceManager\ServiceLocatorInterface;
class ProjectMapperFactory {
public function __invoke(ServiceLocatorInterface $serviceManager) {
$mapper = new ProjectMapper();
$mapper->setDbAdapter($serviceManager->get('PortfolioDbAdapter_V2'));
$mapper->setEntityPrototype($serviceManager->get('Portfolio\V2\Rest\Project\ProjectEntity'));
$projectHydrator = $serviceManager->get('HydratorManager')->get('Portfolio\\V2\\Rest\\Project\\ProjectHydrator');
$mapper->setHydrator($projectHydrator);
return $mapper;
}
}
namespace Portfolio\V2\Rest\Project;
use ZfcBase\Mapper\AbstractDbMapper;
use Zend\Paginator\Adapter\DbSelect;
use Zend\Db\ResultSet\HydratingResultSet;
class ProjectMapper extends AbstractDbMapper {
...
/**
* Provides a collection of all the available projects.
*
* @return \Portfolio\V2\Rest\Project\ProjectCollection
*/
public function findAll() {
$resultSetPrototype = new HydratingResultSet(
$this->getHydrator(),
$this->getEntityPrototype()
);
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter, $resultSetPrototype);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
/**
* Provides a project by ID.
*
* @param int $id
* @return \Portfolio\V2\Rest\Project\ProjectEntity
*/
public function findById($id) {
$select = $this->getSelect();
$select->where(array(
'id' => $id,
));
$entity = $this->select($select)->current();
return $entity;
}
...
}
编辑为:
public function getProjects() {
$projects = $this->getMapper()->findAll();
foreach ($projects as $key => $project) {
$images = $this->getImageService()->getImagesForProject($project['id']);
$projects[$key]['images'] = $images;
}
return $projects;
}
public function findAll() {
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter);
// @todo Replace the constants with data from the config and request.
$projects = $paginatorAdapter->getItems(0, 2);
$projects = $projects->toArray();
return $projects;
}
现在我得到了想要的输出:
{
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects"
}
},
"_embedded": {
"projects": [
{
"id": "1",
"title": "...",
...
"_embedded": {
"images": [
{
"id": "1",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/1"
}
}
},
{
...
},
{
...
}
]
},
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
},
{
"id": "2",
"title": "...",
...
"_embedded": {
"images": [
...
]
},
...
}
]
},
"total_items": 2
}
但这是一个有点糟糕的解决方案,不是吗?我实际上在做的是:我只是在替换Apigility数据检索功能的一部分。。。无论如何,我不喜欢这个解决方案,我想找到一个更好的解决方案(“符合Apigility的解决方案”)。我没有使用db mapper的经验,但我想我可以为您回答问题2
如果提取的项目资源(数组)具有一个键images
,该键保存类型为Hal\Collection
的对象,它将自动提取该集合,并按照您在Hal示例中所示进行渲染
之所以出现这种“魔力”,是因为在Hal.php
中的renderEntity
方法中调用了extractedembeddedcollection
编辑
你写下你想要的:
["images": {...}, {...}, {...}]
但你真正应该做到的是:
{
"id": "2",
"title": "...",
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/2"
}
},
"_embedded": {
"images": [
{...},
{...},
{...}
]
}
}
如何提取对象?您是否在元数据映射中注册了一个查询器
您应该尝试返回如下内容:
ProjectCollection extends Paginator
ProjectEntity
ProjectMapper extends AbstractDbMapper
ProjectService implements ServiceManagerAwareInterface
ProjectServiceFactory implements FactoryInterface
use ZF\Hal\Collection
...
$images = new Collection($arrayOfImages);
$project['images'] = $images;
然后它应该会起作用(我不知道如何解释它)。我终于找到了解决方案。(再次感谢@在GitHub上的支持。)简言之,我们的想法是在水合步骤上使用嵌套的(图像
)项目列表来丰富(项目
)列表项目。我其实不太喜欢这种方式,因为对我来说,在水合水平上有太多的模型逻辑。但它是有效的。我们开始:
/module/Portfolio/config/module.config.php
{
"id": "1",
"title": "...",
...
"_embedded": {
"images": [
{
"id": "1",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/1"
}
}
},
{
"id": "2",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/2"
}
}
},
{
"id": "3",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/3"
}
}
}
]
},
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
}
{
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects?page=1"
},
"first": {
"href": "http://myproject-api.misc.loc/projects"
},
"last": {
"href": "http://myproject-api.misc.loc/projects?page=24"
},
"next": {
"href": "http://myproject-api.misc.loc/projects?page=2"
}
},
"_embedded": {
"projects": [
{
"id": "1",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
},
{
"id": "2",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/2"
}
}
},
{
"id": "3",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/3"
}
}
}
]
},
"page_count": 24,
"page_size": 3,
"total_items": 72
}
public function findAll() {
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
return array(
...
'zf-hal' => array(
'metadata_map' => array(
...
'Portfolio\\V2\\Rest\\Project\\ProjectEntity' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'hydrator' => 'Portfolio\\V2\\Rest\\Project\\ProjectHydrator',
),
'Portfolio\\V2\\Rest\\Project\\ProjectCollection' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'is_collection' => true,
),
...
),
),
);
class Module implements ApigilityProviderInterface {
...
public function getHydratorConfig() {
return array(
'factories' => array(
// V2
'Portfolio\\V2\\Rest\\Project\\ProjectHydrator' => function(ServiceManager $serviceManager) {
$projectHydrator = new ProjectHydrator();
$projectHydrator->setImageService($serviceManager->getServiceLocator()->get('Portfolio\V2\Rest\ImageService'));
return $projectHydrator;
}
),
);
}
...
}
namespace Portfolio\V2\Rest\Project;
use Zend\Stdlib\Hydrator\ClassMethods;
use Portfolio\V2\Rest\Image\ImageService;
class ProjectHydrator extends ClassMethods {
/**
* @var ImageService
*/
protected $imageService;
/**
* @return ImageService the $imageService
*/
public function getImageService() {
return $this->imageService;
}
/**
* @param ImageService $imageService
*/
public function setImageService(ImageService $imageService) {
$this->imageService = $imageService;
return $this;
}
/*
* Doesn't need to be implemented:
* the ClassMethods#hydrate(...) handle the $data already as wished.
*/
/*
public function hydrate(array $data, $object) {
$object = parent::hydrate($data, $object);
if ($object->getId() !== null) {
$images = $this->imageService->getImagesForProject($object->getId());
$object->setImages($images);
}
return $object;
}
*/
/**
* @see \Zend\Stdlib\Hydrator\ClassMethods::extract()
*/
public function extract($object) {
$array = parent::extract($object);
if ($array['id'] !== null) {
$images = $this->imageService->getImagesForProject($array['id']);
$array['images'] = $images;
}
return $array;
}
}
namespace Portfolio\V2\Rest\Project;
use Zend\ServiceManager\ServiceLocatorInterface;
class ProjectMapperFactory {
public function __invoke(ServiceLocatorInterface $serviceManager) {
$mapper = new ProjectMapper();
$mapper->setDbAdapter($serviceManager->get('PortfolioDbAdapter_V2'));
$mapper->setEntityPrototype($serviceManager->get('Portfolio\V2\Rest\Project\ProjectEntity'));
$projectHydrator = $serviceManager->get('HydratorManager')->get('Portfolio\\V2\\Rest\\Project\\ProjectHydrator');
$mapper->setHydrator($projectHydrator);
return $mapper;
}
}
namespace Portfolio\V2\Rest\Project;
use ZfcBase\Mapper\AbstractDbMapper;
use Zend\Paginator\Adapter\DbSelect;
use Zend\Db\ResultSet\HydratingResultSet;
class ProjectMapper extends AbstractDbMapper {
...
/**
* Provides a collection of all the available projects.
*
* @return \Portfolio\V2\Rest\Project\ProjectCollection
*/
public function findAll() {
$resultSetPrototype = new HydratingResultSet(
$this->getHydrator(),
$this->getEntityPrototype()
);
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter, $resultSetPrototype);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
/**
* Provides a project by ID.
*
* @param int $id
* @return \Portfolio\V2\Rest\Project\ProjectEntity
*/
public function findById($id) {
$select = $this->getSelect();
$select->where(array(
'id' => $id,
));
$entity = $this->select($select)->current();
return $entity;
}
...
}
Portfolio\Module
{
"id": "1",
"title": "...",
...
"_embedded": {
"images": [
{
"id": "1",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/1"
}
}
},
{
"id": "2",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/2"
}
}
},
{
"id": "3",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/3"
}
}
}
]
},
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
}
{
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects?page=1"
},
"first": {
"href": "http://myproject-api.misc.loc/projects"
},
"last": {
"href": "http://myproject-api.misc.loc/projects?page=24"
},
"next": {
"href": "http://myproject-api.misc.loc/projects?page=2"
}
},
"_embedded": {
"projects": [
{
"id": "1",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
},
{
"id": "2",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/2"
}
}
},
{
"id": "3",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/3"
}
}
}
]
},
"page_count": 24,
"page_size": 3,
"total_items": 72
}
public function findAll() {
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
return array(
...
'zf-hal' => array(
'metadata_map' => array(
...
'Portfolio\\V2\\Rest\\Project\\ProjectEntity' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'hydrator' => 'Portfolio\\V2\\Rest\\Project\\ProjectHydrator',
),
'Portfolio\\V2\\Rest\\Project\\ProjectCollection' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'is_collection' => true,
),
...
),
),
);
class Module implements ApigilityProviderInterface {
...
public function getHydratorConfig() {
return array(
'factories' => array(
// V2
'Portfolio\\V2\\Rest\\Project\\ProjectHydrator' => function(ServiceManager $serviceManager) {
$projectHydrator = new ProjectHydrator();
$projectHydrator->setImageService($serviceManager->getServiceLocator()->get('Portfolio\V2\Rest\ImageService'));
return $projectHydrator;
}
),
);
}
...
}
namespace Portfolio\V2\Rest\Project;
use Zend\Stdlib\Hydrator\ClassMethods;
use Portfolio\V2\Rest\Image\ImageService;
class ProjectHydrator extends ClassMethods {
/**
* @var ImageService
*/
protected $imageService;
/**
* @return ImageService the $imageService
*/
public function getImageService() {
return $this->imageService;
}
/**
* @param ImageService $imageService
*/
public function setImageService(ImageService $imageService) {
$this->imageService = $imageService;
return $this;
}
/*
* Doesn't need to be implemented:
* the ClassMethods#hydrate(...) handle the $data already as wished.
*/
/*
public function hydrate(array $data, $object) {
$object = parent::hydrate($data, $object);
if ($object->getId() !== null) {
$images = $this->imageService->getImagesForProject($object->getId());
$object->setImages($images);
}
return $object;
}
*/
/**
* @see \Zend\Stdlib\Hydrator\ClassMethods::extract()
*/
public function extract($object) {
$array = parent::extract($object);
if ($array['id'] !== null) {
$images = $this->imageService->getImagesForProject($array['id']);
$array['images'] = $images;
}
return $array;
}
}
namespace Portfolio\V2\Rest\Project;
use Zend\ServiceManager\ServiceLocatorInterface;
class ProjectMapperFactory {
public function __invoke(ServiceLocatorInterface $serviceManager) {
$mapper = new ProjectMapper();
$mapper->setDbAdapter($serviceManager->get('PortfolioDbAdapter_V2'));
$mapper->setEntityPrototype($serviceManager->get('Portfolio\V2\Rest\Project\ProjectEntity'));
$projectHydrator = $serviceManager->get('HydratorManager')->get('Portfolio\\V2\\Rest\\Project\\ProjectHydrator');
$mapper->setHydrator($projectHydrator);
return $mapper;
}
}
namespace Portfolio\V2\Rest\Project;
use ZfcBase\Mapper\AbstractDbMapper;
use Zend\Paginator\Adapter\DbSelect;
use Zend\Db\ResultSet\HydratingResultSet;
class ProjectMapper extends AbstractDbMapper {
...
/**
* Provides a collection of all the available projects.
*
* @return \Portfolio\V2\Rest\Project\ProjectCollection
*/
public function findAll() {
$resultSetPrototype = new HydratingResultSet(
$this->getHydrator(),
$this->getEntityPrototype()
);
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter, $resultSetPrototype);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
/**
* Provides a project by ID.
*
* @param int $id
* @return \Portfolio\V2\Rest\Project\ProjectEntity
*/
public function findById($id) {
$select = $this->getSelect();
$select->where(array(
'id' => $id,
));
$entity = $this->select($select)->current();
return $entity;
}
...
}
Portfolio\V2\Rest\Project\projector
{
"id": "1",
"title": "...",
...
"_embedded": {
"images": [
{
"id": "1",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/1"
}
}
},
{
"id": "2",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/2"
}
}
},
{
"id": "3",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/3"
}
}
}
]
},
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
}
{
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects?page=1"
},
"first": {
"href": "http://myproject-api.misc.loc/projects"
},
"last": {
"href": "http://myproject-api.misc.loc/projects?page=24"
},
"next": {
"href": "http://myproject-api.misc.loc/projects?page=2"
}
},
"_embedded": {
"projects": [
{
"id": "1",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
},
{
"id": "2",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/2"
}
}
},
{
"id": "3",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/3"
}
}
}
]
},
"page_count": 24,
"page_size": 3,
"total_items": 72
}
public function findAll() {
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
return array(
...
'zf-hal' => array(
'metadata_map' => array(
...
'Portfolio\\V2\\Rest\\Project\\ProjectEntity' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'hydrator' => 'Portfolio\\V2\\Rest\\Project\\ProjectHydrator',
),
'Portfolio\\V2\\Rest\\Project\\ProjectCollection' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'is_collection' => true,
),
...
),
),
);
class Module implements ApigilityProviderInterface {
...
public function getHydratorConfig() {
return array(
'factories' => array(
// V2
'Portfolio\\V2\\Rest\\Project\\ProjectHydrator' => function(ServiceManager $serviceManager) {
$projectHydrator = new ProjectHydrator();
$projectHydrator->setImageService($serviceManager->getServiceLocator()->get('Portfolio\V2\Rest\ImageService'));
return $projectHydrator;
}
),
);
}
...
}
namespace Portfolio\V2\Rest\Project;
use Zend\Stdlib\Hydrator\ClassMethods;
use Portfolio\V2\Rest\Image\ImageService;
class ProjectHydrator extends ClassMethods {
/**
* @var ImageService
*/
protected $imageService;
/**
* @return ImageService the $imageService
*/
public function getImageService() {
return $this->imageService;
}
/**
* @param ImageService $imageService
*/
public function setImageService(ImageService $imageService) {
$this->imageService = $imageService;
return $this;
}
/*
* Doesn't need to be implemented:
* the ClassMethods#hydrate(...) handle the $data already as wished.
*/
/*
public function hydrate(array $data, $object) {
$object = parent::hydrate($data, $object);
if ($object->getId() !== null) {
$images = $this->imageService->getImagesForProject($object->getId());
$object->setImages($images);
}
return $object;
}
*/
/**
* @see \Zend\Stdlib\Hydrator\ClassMethods::extract()
*/
public function extract($object) {
$array = parent::extract($object);
if ($array['id'] !== null) {
$images = $this->imageService->getImagesForProject($array['id']);
$array['images'] = $images;
}
return $array;
}
}
namespace Portfolio\V2\Rest\Project;
use Zend\ServiceManager\ServiceLocatorInterface;
class ProjectMapperFactory {
public function __invoke(ServiceLocatorInterface $serviceManager) {
$mapper = new ProjectMapper();
$mapper->setDbAdapter($serviceManager->get('PortfolioDbAdapter_V2'));
$mapper->setEntityPrototype($serviceManager->get('Portfolio\V2\Rest\Project\ProjectEntity'));
$projectHydrator = $serviceManager->get('HydratorManager')->get('Portfolio\\V2\\Rest\\Project\\ProjectHydrator');
$mapper->setHydrator($projectHydrator);
return $mapper;
}
}
namespace Portfolio\V2\Rest\Project;
use ZfcBase\Mapper\AbstractDbMapper;
use Zend\Paginator\Adapter\DbSelect;
use Zend\Db\ResultSet\HydratingResultSet;
class ProjectMapper extends AbstractDbMapper {
...
/**
* Provides a collection of all the available projects.
*
* @return \Portfolio\V2\Rest\Project\ProjectCollection
*/
public function findAll() {
$resultSetPrototype = new HydratingResultSet(
$this->getHydrator(),
$this->getEntityPrototype()
);
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter, $resultSetPrototype);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
/**
* Provides a project by ID.
*
* @param int $id
* @return \Portfolio\V2\Rest\Project\ProjectEntity
*/
public function findById($id) {
$select = $this->getSelect();
$select->where(array(
'id' => $id,
));
$entity = $this->select($select)->current();
return $entity;
}
...
}
Portfolio\V2\Rest\Project\ProjectMapperFactory
{
"id": "1",
"title": "...",
...
"_embedded": {
"images": [
{
"id": "1",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/1"
}
}
},
{
"id": "2",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/2"
}
}
},
{
"id": "3",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/3"
}
}
}
]
},
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
}
{
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects?page=1"
},
"first": {
"href": "http://myproject-api.misc.loc/projects"
},
"last": {
"href": "http://myproject-api.misc.loc/projects?page=24"
},
"next": {
"href": "http://myproject-api.misc.loc/projects?page=2"
}
},
"_embedded": {
"projects": [
{
"id": "1",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
},
{
"id": "2",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/2"
}
}
},
{
"id": "3",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/3"
}
}
}
]
},
"page_count": 24,
"page_size": 3,
"total_items": 72
}
public function findAll() {
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
return array(
...
'zf-hal' => array(
'metadata_map' => array(
...
'Portfolio\\V2\\Rest\\Project\\ProjectEntity' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'hydrator' => 'Portfolio\\V2\\Rest\\Project\\ProjectHydrator',
),
'Portfolio\\V2\\Rest\\Project\\ProjectCollection' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'is_collection' => true,
),
...
),
),
);
class Module implements ApigilityProviderInterface {
...
public function getHydratorConfig() {
return array(
'factories' => array(
// V2
'Portfolio\\V2\\Rest\\Project\\ProjectHydrator' => function(ServiceManager $serviceManager) {
$projectHydrator = new ProjectHydrator();
$projectHydrator->setImageService($serviceManager->getServiceLocator()->get('Portfolio\V2\Rest\ImageService'));
return $projectHydrator;
}
),
);
}
...
}
namespace Portfolio\V2\Rest\Project;
use Zend\Stdlib\Hydrator\ClassMethods;
use Portfolio\V2\Rest\Image\ImageService;
class ProjectHydrator extends ClassMethods {
/**
* @var ImageService
*/
protected $imageService;
/**
* @return ImageService the $imageService
*/
public function getImageService() {
return $this->imageService;
}
/**
* @param ImageService $imageService
*/
public function setImageService(ImageService $imageService) {
$this->imageService = $imageService;
return $this;
}
/*
* Doesn't need to be implemented:
* the ClassMethods#hydrate(...) handle the $data already as wished.
*/
/*
public function hydrate(array $data, $object) {
$object = parent::hydrate($data, $object);
if ($object->getId() !== null) {
$images = $this->imageService->getImagesForProject($object->getId());
$object->setImages($images);
}
return $object;
}
*/
/**
* @see \Zend\Stdlib\Hydrator\ClassMethods::extract()
*/
public function extract($object) {
$array = parent::extract($object);
if ($array['id'] !== null) {
$images = $this->imageService->getImagesForProject($array['id']);
$array['images'] = $images;
}
return $array;
}
}
namespace Portfolio\V2\Rest\Project;
use Zend\ServiceManager\ServiceLocatorInterface;
class ProjectMapperFactory {
public function __invoke(ServiceLocatorInterface $serviceManager) {
$mapper = new ProjectMapper();
$mapper->setDbAdapter($serviceManager->get('PortfolioDbAdapter_V2'));
$mapper->setEntityPrototype($serviceManager->get('Portfolio\V2\Rest\Project\ProjectEntity'));
$projectHydrator = $serviceManager->get('HydratorManager')->get('Portfolio\\V2\\Rest\\Project\\ProjectHydrator');
$mapper->setHydrator($projectHydrator);
return $mapper;
}
}
namespace Portfolio\V2\Rest\Project;
use ZfcBase\Mapper\AbstractDbMapper;
use Zend\Paginator\Adapter\DbSelect;
use Zend\Db\ResultSet\HydratingResultSet;
class ProjectMapper extends AbstractDbMapper {
...
/**
* Provides a collection of all the available projects.
*
* @return \Portfolio\V2\Rest\Project\ProjectCollection
*/
public function findAll() {
$resultSetPrototype = new HydratingResultSet(
$this->getHydrator(),
$this->getEntityPrototype()
);
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter, $resultSetPrototype);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
/**
* Provides a project by ID.
*
* @param int $id
* @return \Portfolio\V2\Rest\Project\ProjectEntity
*/
public function findById($id) {
$select = $this->getSelect();
$select->where(array(
'id' => $id,
));
$entity = $this->select($select)->current();
return $entity;
}
...
}
Portfolio\V2\Rest\Project\ProjectMapper
{
"id": "1",
"title": "...",
...
"_embedded": {
"images": [
{
"id": "1",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/1"
}
}
},
{
"id": "2",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/2"
}
}
},
{
"id": "3",
"project_id": "1",
"title": "...",
...
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/images/3"
}
}
}
]
},
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
}
{
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects?page=1"
},
"first": {
"href": "http://myproject-api.misc.loc/projects"
},
"last": {
"href": "http://myproject-api.misc.loc/projects?page=24"
},
"next": {
"href": "http://myproject-api.misc.loc/projects?page=2"
}
},
"_embedded": {
"projects": [
{
"id": "1",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/1"
}
}
},
{
"id": "2",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/2"
}
}
},
{
"id": "3",
"title": "...",
... <-- HERE I WANT TO GET ["images": {...}, {...}, {...}]
"_links": {
"self": {
"href": "http://myproject-api.misc.loc/projects/3"
}
}
}
]
},
"page_count": 24,
"page_size": 3,
"total_items": 72
}
public function findAll() {
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
return array(
...
'zf-hal' => array(
'metadata_map' => array(
...
'Portfolio\\V2\\Rest\\Project\\ProjectEntity' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'hydrator' => 'Portfolio\\V2\\Rest\\Project\\ProjectHydrator',
),
'Portfolio\\V2\\Rest\\Project\\ProjectCollection' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
'is_collection' => true,
),
...
),
),
);
class Module implements ApigilityProviderInterface {
...
public function getHydratorConfig() {
return array(
'factories' => array(
// V2
'Portfolio\\V2\\Rest\\Project\\ProjectHydrator' => function(ServiceManager $serviceManager) {
$projectHydrator = new ProjectHydrator();
$projectHydrator->setImageService($serviceManager->getServiceLocator()->get('Portfolio\V2\Rest\ImageService'));
return $projectHydrator;
}
),
);
}
...
}
namespace Portfolio\V2\Rest\Project;
use Zend\Stdlib\Hydrator\ClassMethods;
use Portfolio\V2\Rest\Image\ImageService;
class ProjectHydrator extends ClassMethods {
/**
* @var ImageService
*/
protected $imageService;
/**
* @return ImageService the $imageService
*/
public function getImageService() {
return $this->imageService;
}
/**
* @param ImageService $imageService
*/
public function setImageService(ImageService $imageService) {
$this->imageService = $imageService;
return $this;
}
/*
* Doesn't need to be implemented:
* the ClassMethods#hydrate(...) handle the $data already as wished.
*/
/*
public function hydrate(array $data, $object) {
$object = parent::hydrate($data, $object);
if ($object->getId() !== null) {
$images = $this->imageService->getImagesForProject($object->getId());
$object->setImages($images);
}
return $object;
}
*/
/**
* @see \Zend\Stdlib\Hydrator\ClassMethods::extract()
*/
public function extract($object) {
$array = parent::extract($object);
if ($array['id'] !== null) {
$images = $this->imageService->getImagesForProject($array['id']);
$array['images'] = $images;
}
return $array;
}
}
namespace Portfolio\V2\Rest\Project;
use Zend\ServiceManager\ServiceLocatorInterface;
class ProjectMapperFactory {
public function __invoke(ServiceLocatorInterface $serviceManager) {
$mapper = new ProjectMapper();
$mapper->setDbAdapter($serviceManager->get('PortfolioDbAdapter_V2'));
$mapper->setEntityPrototype($serviceManager->get('Portfolio\V2\Rest\Project\ProjectEntity'));
$projectHydrator = $serviceManager->get('HydratorManager')->get('Portfolio\\V2\\Rest\\Project\\ProjectHydrator');
$mapper->setHydrator($projectHydrator);
return $mapper;
}
}
namespace Portfolio\V2\Rest\Project;
use ZfcBase\Mapper\AbstractDbMapper;
use Zend\Paginator\Adapter\DbSelect;
use Zend\Db\ResultSet\HydratingResultSet;
class ProjectMapper extends AbstractDbMapper {
...
/**
* Provides a collection of all the available projects.
*
* @return \Portfolio\V2\Rest\Project\ProjectCollection
*/
public function findAll() {
$resultSetPrototype = new HydratingResultSet(
$this->getHydrator(),
$this->getEntityPrototype()
);
$select = $this->getSelect();
$adapter = $this->getDbAdapter();
$paginatorAdapter = new DbSelect($select, $adapter, $resultSetPrototype);
$collection = new ProjectCollection($paginatorAdapter);
return $collection;
}
/**
* Provides a project by ID.
*
* @param int $id
* @return \Portfolio\V2\Rest\Project\ProjectEntity
*/
public function findById($id) {
$select = $this->getSelect();
$select->where(array(
'id' => $id,
));
$entity = $this->select($select)->current();
return $entity;
}
...
}
正如我在GitHub上的帖子中所说的,如果能从Apigility核心团队得到反馈就太好了,无论这个解决方案是否“符合Apigility标准”,如果不是,还有什么更好的/正确的解决方案。感谢您的回答!我终于让它工作了--几乎。。。我的实体Project
具有属性images,但其类型为Zend\Paginator\Paginator
。它适用于单个对象:这意味着,/project/:id
提供一个项目及其映像:{“id”:“1”,“title”:“foo”,“_embedded”:{“images”:[{image1},{image2},{image3}}
。(这对我来说意味着:Paginator
作为集合父类的变体可以工作。)但它不适用于/project
——当我请求项目列表时,它的项不包含嵌入的图像列表(请参见编辑)。你知道,如何让它也工作吗?为了避免误解,我将我的评论部分编号:1<代码>你想写什么就写什么。。。但是你真正的目标是…
——确切地说,我指的是嵌入\u的正确HAL
格式。2.“您在元数据映射中注册了水合器了吗?”--是的,我正在使用Zend\\Stdlib\\hydrator\\ClassMethods
。3.“如何提取对象?”--请查看我的编辑。4.您的收藏建议:问题是,我无法遍历ZF\Hal\collection
并修改其项目。您好,我面临着同样的问题,到目前为止,您是否找到了合适的解决方案?您好@JimitShah,这对我来说是一个合适的解决方案。我仍然不知道是否有更好/更优雅的,但至少这一个有效。