

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 第 3 適用於 PHP 的 AWS SDK 版中使用分頁結果
<a name="guide_paginators"></a>

有些 AWS 服務操作會分頁，並以截斷的結果回應。例如，Amazon S3`ListObjects` 操作一次最多只會傳回 1，000 個物件。類似這些 (名稱前方通常會加上「列出」或「描述」) 的操作需要以字符 (或標記) 參數進行後續請求，以擷取整組結果。

 **分頁程式**是 的一項功能 適用於 PHP 的 AWS SDK ，可做為此程序的抽象概念，讓開發人員更輕鬆地使用分頁 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";
    }
}
```

## 分頁程式物件
<a name="paginator-objects"></a>

`getPaginator()` 方法傳回的物件是 `Aws\ResultPaginator` 類別的執行個體。此類別會實作 PHP 原生 `iterator` 界面，使其能與 `foreach` 搭配運作。其亦可用於疊代運算函數如 `iterator_to_array`，以及整合 [SPL 疊代運算](http://www.php.net/manual/en/spl.iterators.php)如 `LimitIterator` 物件。

分頁程式物件一次只能保留一個結果的「頁面」，並且會延遲執行。這表示它們只會執行所需的請求，以產生結果的目前頁面。例如，Amazon S3`ListObjects` 操作一次最多只會傳回 1，000 個物件，因此如果您的儲存貯體有 \$110，000 個物件，分頁器就需要執行總共 10 個請求。當您逐一查看結果時，第一個請求會在您開始查看時執行，第二個請求在第二次查看時執行，以此類推。

## 從結果列舉資料
<a name="enumerating-data-from-results"></a>

分頁程式物件有一個名為 `search()` 的方法，這可讓您為一組結果中的資料建立疊代運算。當您呼叫 `search()` 時，請提供 [JMESPath 表達式](guide_jmespath.md)以指定要擷取的資料。呼叫 `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";
}
```

## 非同步分頁
<a name="async-paginators"></a>

您可以提供 `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 操作的結果進行分頁，同時以非同步方式傳送其他請求。

底層以 coroutine 為基礎的承諾將會產生來自回呼的非 null 傳回值。這表示您可以從回呼傳回承諾，此回呼必須先解決再能繼續逐一查看其餘項目，基本上就是合併其他承諾至逐一查看。回呼傳回的最後一個非 null 值，是履行承諾至任何下游承諾的結果。如果上個傳回值是一個承諾，該承諾的解析度是履行或拒絕下游承諾的結果。

```
// 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();
```