Как получить доступ и управлять данными в Apigility перед их отправкой клиенту?

Я разрабатываю Apigility управляемое приложение на основе Zend Framework 2.

В настоящее время я отправляю данные, извлеченные из базы данных, непосредственно клиенту: MyResource#fetch(...) или же MyResource#fetchAll(...) срабатывает и вызывает соответствующий метод на MyService класс, который вызывает MyMapper удалить данные с помощью таких методов, как findFooByBar(...),

Теперь я хотел бы обработать данные перед отправкой ответа. Как я могу это сделать?


Документация Apigility ZF HAL показывает, как получить доступ к данным объекта, между которыми они были получены и отправлены клиенту. Ну, я попробовал это. Это некрасиво и много кода для такой задачи. И … это не работает. Я хочу, однако, опубликовать здесь мое сообщение:

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

...

}

1

Решение

Я думаю, используя renderEntity а также renderCollection События не являются правильным местом для добавления такого рода логики для конкретного ресурса. Это больше подходит для более общих изменений или случайной настройки.

Вы можете добавить эту логику для ваших слушателей ресурса. Так в вашем fetch а также fetchAll методы в вашем MyResource класс вы можете добавить пользовательский код, который вы в настоящее время добавили в эти 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;
}

/* ... */
}
0

Другие решения

Одним из возможных решений является обработка данных в Гидраторе. Поэтому мы пишем собственный класс 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;
}

}

Это не очень хорошее решение, так как часть логики извлечения модели / данных перемещается в гидратор. Но это работает. Вот показана реализация этого подхода и Вот обсуждение этой темы на GitHub.

0

Если вы используете ClassMethods Гидратор и твой Collection продолжается \Zend\Paginator\Paginator Хорошее решение без потери целостности Коллекции и без изменения чьего-либо кода — это перезаписать ваш 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],

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector