msgraph-sdk-php icon indicating copy to clipboard operation
msgraph-sdk-php copied to clipboard

V2 pagination with getValue unclear

Open uncaught opened this issue 1 year ago • 3 comments

The documentation Get a collection of items mentions paging, but the example and code are not entirely clear here.

The call $messages->getValue() from the example would return a native php array type.

Is that array already filled with all items from all pages? Is that guaranteed? Or do I only get a single page here?


On a side note, it might have been better to return a \Generator that can be iterated over, independent on the page size, that will simply call the next page when it's its turn.

uncaught avatar Mar 26 '24 09:03 uncaught

Hi @uncaught , thanks for trying out the SDK.

Is that array already filled with all items from all pages?

No, it only contains a single page.

To get the items on all pages, use the PageIterator, which is described in the next section titled Paging through a collection

Thanks for the feedback on using the \Generator.

SilasKenneth avatar Apr 03 '24 09:04 SilasKenneth

Thank you for your reply!

But so, basically, for every collection, using getValue() is potentially risky because I am in no way forced to deal with pagination. Should you not deprecate this then in favor of a safer method?

My solution is a wrapper around the PageIterator for now:

  public static function iterateCollection(GraphServiceClient $client, Promise $promise): \Generator {
    $pageIterator = new PageIterator($promise->wait(), $client->getRequestAdapter());
    while ($pageIterator->hasNext()) {
      $pageItems = [];
      $pageIterator->iterate(function ($item) use (&$pageItems) {
        $pageItems[] = $item;
      });
      foreach ($pageItems as $pageItem) {
        yield $pageItem;
      }
    }
  }

Obviously this could be implemented cleaner inside the PageIterator without using a callback, but I didn't want to create a fork for this ;)

Example call:

/** @var \Iterator<int, Event> $collection */
$collection = GraphFactory::iterateCollection($graph, $graph->me()->calendarView()->get($config));
foreach ($collection as $event) {
  //...
}

uncaught avatar Apr 04 '24 06:04 uncaught

When using iterateCollection posted by @uncaught and on bigger account (+10 users) after a while a am getting an error invalid_request anybody else with same issue? Any solution for it.

It works perfecty with previus version (V1) of library.

Working sample (V1)

`public function getUsers($filter = null) { $users = []; $this->graph->setApiVersion('v1.0'); $userIterator = $this->graph->createCollectionRequest('GET', '/users' . (is_null($filter) ? '' : $filter)) ->setReturnType(\Microsoft\Graph\Model\User::class) ->setPageSize(100);

while (!$userIterator->isEnd()) {
    $users = array_merge($users, $userIterator->getPage());
}
return $users;

}`

ferizdacic avatar Oct 25 '24 10:10 ferizdacic