Php 在将数据发送到客户端之前,如何访问和操作Apigility中的数据?
我正在基于开发一个受驱动的应用程序 目前,我正在将数据库中检索到的数据直接发送到客户端:一个请求传入,MyResourcefetch。。。或者我的全部。。。获取触发并调用MyService类上的适当方法,该方法调用MyMapper以使用其方法(如findFooByBar…)注销数据 现在我想在发送响应之前处理数据。我该怎么做 显示如何访问已检索并发送给客户端的实体数据。我试过了。这样的任务很难看,而且代码太多。和它不起作用。不过,我想在这里发布我的尝试:Php 在将数据发送到客户端之前,如何访问和操作Apigility中的数据?,php,collections,zend-framework2,laminas-api-tools,Php,Collections,Zend Framework2,Laminas Api Tools,我正在基于开发一个受驱动的应用程序 目前,我正在将数据库中检索到的数据直接发送到客户端:一个请求传入,MyResourcefetch。。。或者我的全部。。。获取触发并调用MyService类上的适当方法,该方法调用MyMapper以使用其方法(如findFooByBar…)注销数据 现在我想在发送响应之前处理数据。我该怎么做 显示如何访问已检索并发送给客户端的实体数据。我试过了。这样的任务很难看,而且代码太多。和它不起作用。不过,我想在这里发布我的尝试: namespace Portfolio;
namespace Portfolio;
...
class Module implements ApigilityProviderInterface {
private $serviceManager;
public function onBootstrap(MvcEvent $event) {
$application = $event->getTarget();
$this->serviceManager = $serviceManager = $application->getServiceManager();
$viewHelperManager = $serviceManager->get('ViewHelperManager');
$hal = $viewHelperManager->get('Hal');
$hal->getEventManager()->attach('renderEntity', array($this, 'onRenderEntity'));
$hal->getEventManager()->attach('renderCollection', array($this, 'onRenderCollection'));
}
public function onRenderEntity($event) {
$entity = $event->getParam('entity');
if ($entity->entity instanceof ProjectEntity) {
$projectEntity = $entity->entity;
$imageCollection = $this->tempCreateimagesForProject(
$event, $entity->entity->getId()
);
$projectEntity->setImages($imageCollection);
$event->setParam('entity', $projectEntity);
}
}
public function onRenderCollection($event) {
$collection = $event->getParam('collection');
$projectCollection = $collection->getCollection();
if ($projectCollection instanceof ProjectCollection) {
foreach ($projectCollection as $key => $projectItem) {
$tempProject = $projectCollection->getItem($key);
$tempProject->append(
['images' => $this->tempCreateimagesForProject($tempProject->offsetGet('id'))]
);
$projectCollection->getItem($key)->offsetSet($key, $tempProject);
}
}
}
private function tempCreateimagesForProject(Event $event, $projectId) {
$imageService = $this->serviceManager->get('Portfolio\V2\Rest\ImageService');
$imageCollection = $imageService->getImagesForProject($projectId);
return $imageCollection;
}
...
}
我认为使用renderEntity和renderCollection事件不是添加这种特定于资源的逻辑的正确位置。它更适合于更一般的更改或附带的定制
您可以将此逻辑添加到资源侦听器中。因此,在MyResource类中的fetch和fetchAll方法中,可以添加当前添加到这些onRenderEntity和onRenderCollection方法中的自定义代码
比如说:
class MyResource extends AbstractResourceListener
{
/**
* Your image service dependency
*/
protected $imageService;
/* ... */
public function fetch($id)
{
$project = $this->projectMapper->fetch($id);
$imageCollection = $this->imageService->getImagesForProject($project);
$project->setImages($imageCollection);
return $project;
}
/* ... */
public function fetchAll($params = array())
{
$projects = $this->projectMapper->fetchAll();
foreach ($projects as $key => $project) {
$imageCollection = $this->imageService->getImagesForProject($project);
$project->setImages($imageCollection);
}
return $projects;
}
/* ... */
}
一种可能的解决方案是处理水合器中的数据。因此,我们编写了一个自定义类,并在其中使用嵌套对象和列表来丰富项目。它可以是这样的:
class MyResource extends AbstractResourceListener
{
/**
* Your image service dependency
*/
protected $imageService;
/* ... */
public function fetch($id)
{
$project = $this->projectMapper->fetch($id);
$imageCollection = $this->imageService->getImagesForProject($project);
$project->setImages($imageCollection);
return $project;
}
/* ... */
public function fetchAll($params = array())
{
$projects = $this->projectMapper->fetchAll();
foreach ($projects as $key => $project) {
$imageCollection = $this->imageService->getImagesForProject($project);
$project->setImages($imageCollection);
}
return $projects;
}
/* ... */
}
公文包\V2\Rest\Project\projector
这不是一个好的解决方案,因为从那时起,模型/数据检索逻辑的一部分被移动到了编辑器中。但它是有效的。显示了此方法的一个实现,并在GitHub上讨论了此主题。如果您使用ClassMethods或,并且您的集合扩展了\Zend\Paginator\Paginator,那么一个好的解决方案是覆盖getCurrentItems方法,而不会丢失集合的一致性,也不会更改任何人的代码
我已经将键命名为一些东西,以免与其他地方的getValue方法混淆
这使“某物”值看起来像[某物]。非常感谢您的回答!公共函数fetch$id{$projectMapper=$this->getServiceManager->get'..\projectMapper';$project=$projectMapper->findById$id;$imageService=$this->getServiceManager->get'..\imageService';$imageCollection=$imageService->getImagesForProject->getId;$project->setImages$imageCollection;返回$project;}在ProjectResource类中,返回希望输出的带有嵌入图像的单个项目。因此,它适用于单个实体。但不适用于收藏。集合是Zend\Paginator\Paginator对象。公共函数fetchAll。。。{…$projects=$projectMapper->findAll;foreach$projects as$key=>$project{$imageCollection=..;$project['images']=$imageCollection;}返回$projects;}返回没有图像的项目,因为我们只处理循环中项目项的副本$项目[$key]->设置图像。。。也没有帮助,因为projects是一个分页器,而不是数组/数组对象。这就是为什么我一直在寻找解决此问题的方法,并在事件中尝试了此方法。你是对的,这不是一个好的解决方案,即使它会起作用。但是,对于资源类的正确解决方案,我们需要对扩展Zend\Paginator\Paginator的集合的数据进行写入访问。如何访问和操作它的数据?@automatix因为我使用了数据库抽象理论,所以在获取嵌入实体中的集合时没有任何问题。您应该尝试在查询中获取并加入集合。不确定如何使用数据库映射器实现这一点。您还可以使用自定义水合器在提取过程中获取集合。但如果你问我,这似乎不正确。
public class MyResourceCollection // most likely extends Paginator
{
public function getCurrentItems()
{
// getting the original items
$items = parent::getCurrentItems();
// as we work with objects $item will be an object
// when working with objects we use references to them not clones of objects
// so changes to $item are also present in the collection
foreach ($collection as $item) {
$oldSomething = $item->getSomething();
$item->setSomething('['.$oldSomething.']');
}
// $items are now changed, return them
return $items;
}
}