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

时间:2015-02-18 16:22:05

标签: php collections zend-framework2 apigility

我正在根据Apigility开发Zend Framework 2驱动的应用程序。

目前,我将数据库中检索到的数据直接发送到客户端:请求进入,MyResource#fetch(...)MyResource#fetchAll(...)被触发,并在{{1}上调用适当的方法} class,调用MyService以使用MyMapper等方法来淘汰数据。

现在我想在发送响应之前处理数据。我怎么能这样做?


Apigility ZF HAL documentation显示,如何检索它之间的实体数据已被检索并发送到客户端。好吧,我试过这个。它的丑陋和许多代码都是为了这样的任务。并且......它不起作用。但是我想在这里发帖,我的出席了:

findFooByBar(...)

3 个答案:

答案 0 :(得分:0)

我认为使用renderEntityrenderCollection事件不是添加此类资源特定逻辑的正确位置。它更适合更一般的更改或偶然的定制。

您可以将此逻辑添加到资源侦听器。因此,在fetch课程的fetchAllMyResource方法中,您可以添加当前在这些onRenderEntityonRenderCollection方法中添加的自定义代码。

这样的事情:

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

    /* ... */
}

答案 1 :(得分:0)

一种可能的解决方案是处理Hydrator中的数据。因此,我们编写一个自定义的Hydrator类,并使用嵌套对象和列表来丰富项目。它看起来像这样:

<强> Portfolio\V2\Rest\Project\ProjectHydrator

...

class ProjectHydrator extends ClassMethods {

    /**
     * @var ImageService
     */
    protected $imageService;

    ...

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

}

这不是一个好的解决方案,因为那时模型/数据检索逻辑的一部分被移动到水化器。但它的确有效。 Here显示了此方法的实现,here是对GitHub上此主题的讨论。

答案 2 :(得分:0)

如果您正在使用ClassMethods Hydrator并且Collection扩展\Zend\Paginator\Paginator一个不错的解决方案而不会失去Collection的一致性并且不更改任何人的代码就是覆盖 getCurrentItems() 方法。

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

我已将密钥something命名为不与其他地方的getValue方法混淆。

这使something值看起来像[something]