版本 3 中的分页器 AWS SDK for PHP - AWS SDK for PHP

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

版本 3 中的分页器 AWS SDK for PHP

某些 AWS 服务操作会被分页并以截断结果作为响应。例如,Amazon S3ListObjects 操作每次最多只能返回 1000 个对象。与此类似的操作(前缀通常为“list”或“describe”)需要利用令牌(或标记)参数生成后续请求,以检索完整的结果集。

分页器是其中的一项功能,它 AWS SDK for PHP 可以作为对这个过程的抽象,使开发人员更容易使用分页。APIs分页工具本质上是结果的迭代器。它们是使用客户端的 getPaginator() 方法创建的。如果调用 getPaginator(),您必须提供操作名称以及操作的参数(与执行操作时的方法相同)。您可以使用 foreach 迭代分页工具对象,以获得单个 Aws\Result 对象。

$results = $s3Client->getPaginator('ListObjects', [ 'Bucket' => 'amzn-s3-demo-bucket' ]); foreach ($results as $result) { foreach ($result['Contents'] as $object) { echo $object['Key'] . "\n"; } }

分页工具对象

getPaginator() 方法返回的对象是 Aws\ResultPaginator 类的实例。这个类实现PHP了原生iterator接口,这就是它使用的原因foreach。它也可以与迭代器函数(比如)一起使用iterator_to_array,并且可以很好地与SPL对象之类的迭代器集成。LimitIterator

分页工具对象每次只保留一“页”结果,并延时执行。这就意味着,请求数量是根据生成当前的结果页面的需求决定的。例如,Amazon S3ListObjects 操作每次最多只返回 1000 个对象,如果您的存储桶中有约 10000 个对象,分页工具共需执行 10 次请求。如果您需要迭代结果,则会在开始迭代时执行第一个请求,在循环第二次迭代时执行第二个请求,依此类推。

枚举结果数据

分页工具对象拥有名为 search() 的方法,允许您为一组结果中的数据创建迭代器。当您调用时search(),请提供一个JMESPath表达式来指定要提取的数据。调用 search() 会返回迭代器,生成每页结果的表达式结果。在您迭代返回的迭代器时将延时评估。

以下示例与之前的代码示例等效,但使用 ResultPaginator::search() 方法可以更加精确。

$results = $s3Client->getPaginator('ListObjects', [ 'Bucket' => 'amzn-s3-demo-bucket' ]); foreach ($results->search('Contents[].Key') as $key) { echo $key . "\n"; }

JMESPath表达式可以让你做相当复杂的事情。例如,如果您希望打印所有的对象键和常用前缀(即针对存储桶执行 ls),可以执行以下操作。

// List all prefixes ("directories") and objects ("files") in the bucket $results = $s3Client->getPaginator('ListObjects', [ 'Bucket' => 'amzn-s3-demo-bucket', 'Delimiter' => '/' ]); $expression = '[CommonPrefixes[].Prefix, Contents[].Key][]'; foreach ($results->search($expression) as $item) { echo $item . "\n"; }

异步分页

您可以提供 each()Aws\ResultPaginator 方法的回调,异步迭代分页工具的结果。分页工具生成的每个值都会调用该回调。

$results = $s3Client->getPaginator('ListObjects', [ 'Bucket' => 'amzn-s3-demo-bucket' ]); $promise = $results->each(function ($result) { echo 'Got ' . var_export($result, true) . "\n"; });
注意

使用该each()方法可以对API操作结果进行分页,同时异步发送其他请求。

底层基于协同程序的 Promise 会生成回调的非 null 返回值。这就意味着,您可以从回调返回 Promise,而在继续迭代其余项目之前,必须解决该回调,也就是要将其他 Promise 合并到迭代中。回调返回的最后一个非 null 值,是可满足对任何下游 Promise 所做的 Promise 的结果。如果返回的最后一个值是 Promise,解决该 Promise 所得的结果将满足或拒绝下游 Promise。

// Delete all keys that end with "Foo" $promise = $results->each(function ($result) use ($s3Client) { if (substr($result['Key'], -3) === 'Foo') { // Merge this promise into the iterator return $s3Client->deleteAsync([ 'Bucket' => 'amzn-s3-demo-bucket', 'Key' => 'Foo' ]); } }); $promise ->then(function ($result) { // Result would be the last result to the deleteAsync operation }) ->otherwise(function ($reason) { // Reason would be an exception that was encountered either in the // call to deleteAsync or calls performed while iterating }); // Forcing a synchronous wait will also wait on all of the deleteAsync calls $promise->wait();