Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在将数据发送到客户端之前,如何访问和操作Apigility中的数据?_Php_Collections_Zend Framework2_Laminas Api Tools - Fatal编程技术网

Php 在将数据发送到客户端之前,如何访问和操作Apigility中的数据?

Php 在将数据发送到客户端之前,如何访问和操作Apigility中的数据?,php,collections,zend-framework2,laminas-api-tools,Php,Collections,Zend Framework2,Laminas Api Tools,我正在基于开发一个受驱动的应用程序 目前,我正在将数据库中检索到的数据直接发送到客户端:一个请求传入,MyResourcefetch。。。或者我的全部。。。获取触发并调用MyService类上的适当方法,该方法调用MyMapper以使用其方法(如findFooByBar…)注销数据 现在我想在发送响应之前处理数据。我该怎么做 显示如何访问已检索并发送给客户端的实体数据。我试过了。这样的任务很难看,而且代码太多。和它不起作用。不过,我想在这里发布我的尝试: namespace Portfolio;

我正在基于开发一个受驱动的应用程序

目前,我正在将数据库中检索到的数据直接发送到客户端:一个请求传入,MyResourcefetch。。。或者我的全部。。。获取触发并调用MyService类上的适当方法,该方法调用MyMapper以使用其方法(如findFooByBar…)注销数据

现在我想在发送响应之前处理数据。我该怎么做

显示如何访问已检索并发送给客户端的实体数据。我试过了。这样的任务很难看,而且代码太多。和它不起作用。不过,我想在这里发布我的尝试:

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;
    }
}