Невозможно сгенерировать HalResource для объекта типа ArrayObject. - PullRequest
0 голосов
/ 04 июля 2019

У меня проблемы с возвратом объекта paginator в виде HAL-коллекции json. Я использую последние версии zend-expressive и zend-expressive-hal.
Это настройка из моего ConfigProvider:

public function __invoke() : array
{
    return [
        'dependencies' => $this->getDependencies(),
        MetadataMap::class => $this->getHalConfig(),
    ];
}

public function getHalConfig() : array
{
    return [
        [
            '__class__' => RouteBasedCollectionMetadata::class,
            'collection_class' => RoleCollection::class,
            'collection_relation' => 'user_roles',
            'route' => 'api.user.roles',
        ],
    ];
}

А вот мои методы-обработчики:

public function get(ServerRequestInterface $request) : ResponseInterface
{
    // read some records from the database
    $select = new Select();
    $select->from(['r' => 'user_roles']);
    $select->columns(['id', 'name']);

    $paginator = new RoleCollection(new DbSelect($select, $this->dbAdapter));
    $paginator->setItemCountPerPage(25);
    $paginator->setCurrentPageNumber(1);

    return $this->createResponse($request, $paginator);
}

private function createResponse(ServerRequestInterface $request, $instance) : ResponseInterface
{
    return $this->responseFactory->createResponse(
        $request,
        $this->resourceGenerator->fromObject($instance, $request)
    );
}

Класс RoleCollection является только наследием Paginator:

class RoleCollection extends Paginator
{
}

Сообщение об ошибке, которое я получаю:

Cannot generate Zend\Expressive\Hal\HalResource for object of type ArrayObject; not in metadata map

1 Ответ

0 голосов
/ 09 июля 2019

Я думаю, что вам не хватает метаданных для самого объекта Role.

Например, это что-то похожее на мой объект сообщения:

MetadataMap::class => [
    [
        '__class__'           => RouteBasedCollectionMetadata::class,
        'collection_class'    => Posts::class,
        'collection_relation' => 'posts',
        'route'               => 'api.posts',
    ],
    [
        '__class__'      => RouteBasedResourceMetadata::class,
        'resource_class' => Post::class,
        'route'          => 'api.posts.view',
        'extractor'      => ArraySerializable::class,
    ],
],

Вы описали только коллекцию, а класс ресурсов отсутствует для одной роли.

Я также вижу, что генератор ресурсов пытается проанализировать ArrayObject. Это должно быть заключено в объект Role, который вы можете добавить в MetadataMap.

Где в вашем коде что-то не так, это строка:

$paginator = new RoleCollection(new DbSelect($select, $this->dbAdapter));

Это добавляет результат запроса в paginator, но paginator не знает, как его обработать. Если я правильно помню, DbSelect возвращает ResultSet. Я предполагаю, что именно отсюда происходит ArrayObject. Вероятно, вам нужно переопределить этот ResultSet и убедиться, что он возвращает массив объектов Role. Возможно, вы захотите взглянуть на адаптер dbselect и набор гидратирующих результатов .

Если у вас есть объект Role в paginator, вы можете описать его в метаданных.

[
    '__class__'      => RouteBasedResourceMetadata::class,
    'resource_class' => UserRole::class,
    'route'          => 'api.roles',
    'extractor'      => ...,
],

Я использую доктрину с hal, поэтому zend-db выходит за рамки моей компетенции. Если вам нужна дополнительная помощь, я предлагаю zf форумы .

...