Amazon SDK for PHP 版本 3 中的分页工具 - Amazon SDK for PHP
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

Amazon SDK for PHP 版本 3 中的分页工具

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

Paginator 是Amazon SDK for PHP的一种功能,充当此流程的抽象层,使开发人员能够更轻松地使用分页的 API。分页工具本质上是结果的迭代器。它们是使用客户端的 getPaginator() 方法创建的。如果调用 getPaginator(),您必须提供操作名称以及操作的参数(与执行操作时的方法相同)。您可以使用 foreach 迭代分页工具对象,以获得单个 Aws\Result 对象。

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

分页工具对象

getPaginator() 方法返回的对象是 Aws\ResultPaginator 类的实例。此类实现 PHP 的原生 iterator 接口,因此它可与 foreach 配合使用。它还可与迭代器函数 (如 iterator_to_array) 结合使用,并与 SPL iterators(如 LimitIterator 对象)良好集成。

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

枚举结果数据

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

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

$results = $s3Client->getPaginator('ListObjects', [ 'Bucket' => 'my-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' => 'my-bucket', 'Delimiter' => '/' ]); $expression = '[CommonPrefixes[].Prefix, Contents[].Key][]'; foreach ($results->search($expression) as $item) { echo $item . "\n"; }

异步分页

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

$results = $s3Client->getPaginator('ListObjects', [ 'Bucket' => 'my-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' => 'my-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();