Limit the results in Apigility

2019-04-30 00:47发布

问题:

I created a code connected API with Apigility. For now I am using the standard create stubs. In my PostResource there is a method called fetchAll($params = array()). I created the code for the method so that it returns a paginatable set of results:

/** @var HydratorInterface $hydrator */
$hydrator = new \Zend\Stdlib\Hydrator\ClassMethods();

/** @var PostService $postService */
$postService = new PostService();

$posts = $postService->findAll(/* Limit, default 10 */);
$apiData = array();
foreach ($posts as $post) {
    $apiData[] = $hydrator->extract($post);
}
return new Paginator(new ArrayAdapter($apiData));

This works fine so far. If i navigate to the API URL I will get a paginated json representation of my DB data. If I set the page size for my API to 5. It will give me 2 pages and 5 results. So far so good. The problem is, that on every call (page 1 or page 2) all 10 results will be fetched from the DB. It only returns 5 at one page but 10 are hydrated etc.

Is there a way to use a limit but also let Apigility or the paginator know, how much results there are in total so that I will get 5 rows and still the pagination?

回答1:

I don't know exactly, how you're retrieving the data, but however the following approach works as wished: The call chain looks like AddressResource#fetchAll(...) -> AddressService#getBar(...) -> AddressMapper#findAll(...) and the data retrieving method returns a Collection object.

AddressResource.php

...

class AddressResource ... {

    ...

    public function fetchAll($params = array()) {
        $service = $this->getAddressService();
        $collection = $service->getAddresses($params->toArray());
        return $collection;
    }

    ...

}

AddressService.php

...

class AddressService ... {

    ...

    public function getAddresses($params = array()) {
        $collection = $this->getMapper()->findAll($params);
        return $collection;
    }

    ...

}

AddressMapper.php

...

class AddressMapper extends AbstractDbMapper {

    ...

    public function findAll($params = array()) {
        $select = $this->getSelect();
        $select->where(
            ...
        );
        $paginatorAdapter = $this->createPaginationAdapter($select);
        $collection = new AddressCollection($paginatorAdapter);
        return $collection;
    }

    ...

}

AddressCollection.php

...

use Zend\Paginator\Paginator;

class AddressCollection extends Paginator {
}

module.config.php

return array(
    ...
    'zf-rest' => array(
        ...
        'AddressBookAPI\\V1\\Rest\\Address\\Controller' => array(
            ...
            'page_size' => 5,
            ...
        ),
        ...
    ),
    ...
);

Now a test: I'm calling /addresses and observing the MySQL query log:

$ tail -f /var/log/mysql_query.log

...

3 Connect   root@localhost on address-book-api
3 Query     SET NAMES 'UTF8'
3 Query     SELECT COUNT(1) AS `C` FROM (SELECT `addresses`.* FROM `addresses`) AS `original_select`
3 Query     SELECT `addresses`.* FROM `addresses` LIMIT 5 OFFSET 0
3 Quit

...