

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

# 从版本 2 迁移 适用于 PHP 的 AWS SDK
<a name="getting-started_migration"></a>

本主题展示如何迁移代码，以使用 适用于 PHP 的 AWS SDK 的版本 3，并介绍新版本与开发工具包版本 2 的不同之处。

**注意**  
开发工具包的基本使用模式（即 `$result = $client->operation($params);`）从版本 2 到版本 3 并未改变，这样可确保顺利迁移。

## 简介
<a name="introduction"></a>

版本 3 适用于 PHP 的 AWS SDK 代表了为改进 SDK 的功能、整合两年多的客户反馈、升级我们的依赖关系、提高性能和采用最新的 PHP 标准所做的巨大努力。

## 版本 3 中有哪些新功能？
<a name="what-s-new-in-version-3"></a>

的第 3 版 适用于 PHP 的 AWS SDK 遵循 [PSR-4 和 PSR-7 标准](http://php-fig.org)，今后将遵循该[SemVer](http://semver.org/)标准。

其他新增功能包括：
+ 用于自定义服务客户端行为的中间件系统
+ 灵活的*分页工具*，用于迭代分页结果
+ 能够通过以下方式从*结果*和*分页器对象中*查询数据 *JMESPath* 
+ 通过 `'debug'` 配置选项轻松调试

### 分离的 HTTP 层
<a name="decoupled-http-layer"></a>
+  默认使用 [Guzzle 6](http://guzzlephp.org) 发送请求，但也支持 Guzzle 5。
+ 在 cURL 不可用的环境中开发工具包也可以工作。
+ 也支持自定义 HTTP 处理程序。

### 异步请求
<a name="asynchronous-requests"></a>
+ *Waiter* 和*分段上传工具*等功能也可异步使用。
+ 使用* Promise *和*协同程序*可创建异步工作流程。
+ 提升了并发或批处理请求的性能。

## 与版本 2 有何不同之处？
<a name="what-s-different-from-version-2"></a>

### 更新了项目依赖项
<a name="project-dependencies-are-updated"></a>

开发工具包在此版本中更改了依赖项。
+ 开发工具包现在需要 PHP 8.1 及以上。可以自由地在开发工具包代码中使用[生成器](http://php.net/manual/en/language.generators.overview.php)。
+ 我们已将 SDK 升级为使用 [Guzzle 6](http://guzzlephp.org)（或 5），它提供了 SDK 用来向服务发送请求的底层 HTTP 客户端实现。 AWS Guzzle 的最新版本引入了一系列改进，包括异步请求、可交换 HTTP 处理程序、PSR-7 合规性、更出色的性能等。
+ 来自 PHP-FIG (`psr/http-message`) 的 PSR-7 包定义了用于表示 HTTP 请求、HTTP 响应和流的接口。 URLs这些接口是开发工具包和 Guzzle 通用的，可与兼容 PSR-7 的其他程序包互通。
+ Guzzle 的 PSR-7 实现 (`guzzlehttp/psr7`) 在 PSR-7 中提供接口实现，还提供若干有用的类和函数。开发工具包和 Guzzle 6 均在很大程度上依赖这个程序包。
+ Guzzle 的 [Promises/A\$1](https://promisesaplus.com) 实现 (`guzzlehttp/promises`) 是开发工具包和 Guzzle 通用的，可提供管理异步请求和协同程序的接口。虽然 Guzzle 的 Multi-curl HTTP 处理程序最终实现了允许异步请求的非阻塞 I/O 模型，但该软件包提供了在该范式中进行编程的能力。有关更多详细信息，请参阅[适用于 PHP 的 AWS SDK 版本 3 中的 Promis](guide_promises.md) es。
+ SDK 中使用 [JMESPath](http://jmespath.org/)(`mtdowling/jmespath.php`) 的 PHP 实现来提供`Aws\Result::search()`和`Aws\ResultPaginator::search()`方法的数据查询能力。有关更多详细信息[，请参阅 适用于 PHP 的 AWS SDK 版本 3 中的JMESPath 表达式](guide_jmespath.md)。

### 现在要求提供区域和版本选项
<a name="region-and-version-options-are-now-required"></a>

如果要将任何服务的客户端实例化，请指定 `'region'` 和 `'version'` 选项。在的版本 2 中 适用于 PHP 的 AWS SDK，`'version'`是完全可选的，有时`'region'`是可选的。在版本 3 中，这两个选项都是必需的。明确说明这两个选项可以让你锁定你要编码的 API 版本和 AWS 区域。当新的 API 版本创建或新的 AWS 区域可用时，在您准备好显式更新配置之前，您将与可能发生的重大更改隔离开来。

**注意**  
如果您不关心所用的 API 版本，只需将 `'version'` 选项设为 `'latest'`。但是，我们建议您针对生产代码显式设置 API 版本号。  
并非所有服务在所有 AWS 地区都可用。您可以参考[区域和端点](https://docs.aws.amazon.com/general/latest/gr/rande.html)，找到可用区域的列表。  
对于只能通过单个全球终端节点提供的服务（例如 Amazon Route 53 和 Amazon CloudFront），请实例化客户端，并将配置的区域设置为。 AWS Identity and Access Management`us-east-1`

**重要**  
SDK 还包括多区域客户端，它们可以根据作为命令参数提供的参数 (`@region`) 将请求分发到不同的 AWS 区域。这些客户端默认使用的区域是由客户端构造函数提供的 `region` 选项指定的。

### 使用构造函数进行客户端实例化
<a name="client-instantiation-uses-the-constructor"></a>

在的版本 3 中 适用于 PHP 的 AWS SDK，实例化客户端的方式发生了变化。您只需使用 `factory` 关键字即可将客户端实例化，而在版本 2 中需使用 `new` 方法。

```
use Aws\DynamoDb\DynamoDbClient;

// Version 2 style
$client = DynamoDbClient::factory([
    'region'  => 'us-east-2'
]);

// Version 3 style
$client = new DynamoDbClient([
    'region'  => 'us-east-2',
    'version' => '2012-08-10'
]);
```

**注意**  
仍可使用 `factory()` 方法将客户端实例化。但这种方法已被弃用。

### 客户端配置已更改
<a name="client-configuration-has-changed"></a>

版本 3 中的客户端配置选项与版本 2 相比略 适用于 PHP 的 AWS SDK 有变化。有关所有支持的选项[的描述，请参阅 适用于 PHP 的 AWS SDK 版本 3 的配置](guide_configuration.md)页面。

**重要**  
在版本 3 中，`'key'` 和 `'secret'` 不再是根级别的有效选项，但可以作为 `'credentials'` 选项的一部分进行传递。我们这样做的原因之一是为了阻止开发人员将 AWS 凭证硬编码到他们的项目中。

#### Sdk 对象
<a name="the-sdk-object"></a>

的版本 3 适用于 PHP 的 AWS SDK 引入了该`Aws\Sdk`对象作为替换对象`Aws\Common\Aws`。`Sdk` 对象可作为客户端工厂，用于管理多个客户端的共享配置选项。

开发工具包版本 2 中的 `Aws` 类像一个服务定位器（它总是会返回客户端的同一实例），而版本 3 中的 `Sdk` 类在每次使用时都会返回客户端的一个新实例。

`Sdk` 对象也不支持与开发工具包版本 2 相同的配置文件格式。原来的配置格式是 Guzzle 3 的特定格式，现已过时。可利用基本数组更轻松地进行配置，配置方法在[使用 Sdk 类](configuring-service-clients-code.md#sdk-class)中进行了记录。

### 更改了一些 API 结果
<a name="some-api-results-have-changed"></a>

为了保持软件开发工具包解析 API 操作结果的方式的一致性，亚马逊 ElastiCache、亚马逊 RDS 和 Amazon Redshift 现在在某些 API 响应上增加了包装元素。

例如，在版本 3 中调用 Amazon RDS [DescribeEngineDefaultParameters](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeEngineDefaultParameters.html)结果现在包括一个封装 “EngineDefaults” 元素。在版本 2 中没有此元素。

```
$client = new Aws\Rds\RdsClient([
    'region'  => 'us-west-1',
    'version' => '2014-09-01'
]);

// Version 2
$result = $client->describeEngineDefaultParameters();
$family = $result['DBParameterGroupFamily'];
$marker = $result['Marker'];

// Version 3
$result = $client->describeEngineDefaultParameters();
$family = $result['EngineDefaults']['DBParameterGroupFamily'];
$marker = $result['EngineDefaults']['Marker'];
```

以下操作会受到影响，在结果输出中会包含包装元素（在下文的括号中提供）：
+ Amazon ElastiCache
  + AuthorizeCacheSecurityGroupIngress (CacheSecurityGroup)
  + CopySnapshot （快照）
  + CreateCacheCluster (CacheCluster)
  + CreateCacheParameterGroup (CacheParameterGroup)
  + CreateCacheSecurityGroup (CacheSecurityGroup)
  + CreateCacheSubnetGroup (CacheSubnetGroup)
  + CreateReplicationGroup (ReplicationGroup)
  + CreateSnapshot （快照）
  + DeleteCacheCluster (CacheCluster)
  + DeleteReplicationGroup (ReplicationGroup)
  + DeleteSnapshot （快照）
  + DescribeEngineDefaultParameters (EngineDefaults)
  + ModifyCacheCluster (CacheCluster)
  + ModifyCacheSubnetGroup (CacheSubnetGroup)
  + ModifyReplicationGroup (ReplicationGroup)
  + PurchaseReservedCacheNodesOffering (ReservedCacheNode)
  + RebootCacheCluster (CacheCluster)
  + RevokeCacheSecurityGroupIngress (CacheSecurityGroup)
+ Amazon RDS
  + AddSourceIdentifierToSubscription (EventSubscription)
  + 授权 DBSecurityGroupIngress （DBSecurity群组）
  + 复制DBParameter组（DBParameter组）
  + 复制 DBSnapshot (DBSnapshot)
  + CopyOptionGroup (OptionGroup)
  + 创建 DBInstance (DBInstance)
  + 创建 DBInstance ReadReplica (DBInstance)
  + 创建DBParameter群组（DBParameter群组）
  + 创建DBSecurity群组（DBSecurity群组）
  + 创建 DBSnapshot (DBSnapshot)
  + 创建DBSubnet群组（DBSubnet群组）
  + CreateEventSubscription (EventSubscription)
  + CreateOptionGroup (OptionGroup)
  + 删除 DBInstance (DBInstance)
  + 删除 DBSnapshot (DBSnapshot)
  + DeleteEventSubscription (EventSubscription)
  + DescribeEngineDefaultParameters (EngineDefaults)
  + 修改 DBInstance (DBInstance)
  + 修改DBSubnet群组（DBSubnet群组）
  + ModifyEventSubscription (EventSubscription)
  + ModifyOptionGroup (OptionGroup)
  + PromoteReadReplica (DBInstance)
  + PurchaseReservedDBInstances发行（已保留DBInstance）
  + 重启 DBInstance (DBInstance)
  + RemoveSourceIdentifierFromSubscription (EventSubscription)
  + DBInstance从 DBSnapshot (DBInstance) 恢复
  + 恢复 DBInstance ToPointInTime (DBInstance)
  + 撤销 DBSecurityGroupIngress （DBSecurity群组）
+ Amazon Redshift
  + AuthorizeClusterSecurityGroupIngress (ClusterSecurityGroup)
  + AuthorizeSnapshotAccess （快照）
  + CopyClusterSnapshot （快照）
  + CreateCluster （集群）
  + CreateClusterParameterGroup (ClusterParameterGroup)
  + CreateClusterSecurityGroup (ClusterSecurityGroup)
  + CreateClusterSnapshot （快照）
  + CreateClusterSubnetGroup (ClusterSubnetGroup)
  + CreateEventSubscription (EventSubscription)
  + CreateHsmClientCertificate (HsmClientCertificate)
  + CreateHsmConfiguration (HsmConfiguration)
  + DeleteCluster （集群）
  + DeleteClusterSnapshot （快照）
  + DescribeDefaultClusterParameters (DefaultClusterParameters)
  + DisableSnapshotCopy （集群）
  + EnableSnapshotCopy （集群）
  + ModifyCluster （集群）
  + ModifyClusterSubnetGroup (ClusterSubnetGroup)
  + ModifyEventSubscription (EventSubscription)
  + ModifySnapshotCopyRetentionPeriod （集群）
  + PurchaseReservedNodeOffering (ReservedNode)
  + RebootCluster （集群）
  + RestoreFromClusterSnapshot （集群）
  + RevokeClusterSecurityGroupIngress (ClusterSecurityGroup)
  + RevokeSnapshotAccess （快照）
  + RotateEncryptionKey （集群）

### 已删除 Enum 类
<a name="enum-classes-have-been-removed"></a>

我们已删除 适用于 PHP 的 AWS SDK版本 2 中的 `Enum` 类（例如 `Aws\S3\Enum\CannedAcl`）。Enum 是开发工具包公共 API 中的具体类，其中包含的常量代表有效参数值的组合。由于这些枚举是特定于某一 API 版本的，是可变的，可能与 PHP 保留关键字冲突，因此并不是非常有用，所以我们在版本 3 中删除了它们，从而支持版本 3 的数据驱动特性，以及与 API 版本无关的特性。

请直接使用文本值，而不是使用 `Enum` 对象的值（例如，`CannedAcl::PUBLIC_READ` → `'public-read'`）。

### 已删除精细异常类
<a name="fine-grained-exception-classes-have-been-removed"></a>

我们已基于与删除 Enum 非常类似的原因，删除了每项服务的命名空间中存在的精细异常类（例如 `Aws\Rds\Exception\{SpecificError}Exception`）。服务或操作引发的异常依赖于所用的 API 版本（各版本可能有变化）。另外，也无法提供给定操作可引发异常的完整列表，从而使版本 2 的精细异常类不完整。

通过捕获每个服务的根异常类来处理错误（例如 `Aws\Rds\Exception\RdsException`）。您可以使用异常的 `getAwsErrorCode()` 方法查看具体的错误代码。它的功能与抓住不同的异常类等效，但不会为开发工具包增加多余内容。

### 已删除静态 Facade 类
<a name="static-facade-classes-have-been-removed"></a>

在的版本2中 适用于 PHP 的 AWS SDK，有一个受Laravel启发的模糊功能，它允许你调用该`Aws`类来启用`enableFacades()`对各种服务客户端的静态访问。此功能不符合 PHP 最佳实践，我们在一年多前停止为此功能提供文档。在版本 3 中完全删除了此功能。请从 `Aws\Sdk` 对象中检索客户端对象，并将其用作对象实例，而不是静态类。

### 分页器取代迭代器
<a name="paginators-supersede-iterators"></a>

的版本 2 适用于 PHP 的 AWS SDK 有一个名为\$1迭代器\$1的功能。这些对象用于迭代分页结果。我们收到反馈，表示它们不够灵活，因为迭代器只会发出每个结果的特定值。如果您需要结果的其他值，只能通过事件侦听器进行检索。

在版本 3 中，[分页工具](guide_paginators.md)替代了迭代器。它们的用途类似，但分页工具更灵活。这是因为分页工具可生成结果对象，而不是响应值。

以下示例演示了在版本 2 和版本 3 中如何检索 `S3 ListObjects` 操作的分页结果，从而展示了分页工具与迭代器的不同之处。

```
// Version 2
$objects = $s3Client->getIterator('ListObjects', ['Bucket' => 'amzn-s3-demo-bucket']);
foreach ($objects as $object) {
    echo $object['Key'] . "\n";
}
```

```
// Version 3
$results = $s3Client->getPaginator('ListObjects', ['Bucket' => 'amzn-s3-demo-bucket']);
foreach ($results as $result) {
    // You can extract any data that you want from the result.
    foreach ($result['Contents'] as $object) {
        echo $object['Key'] . "\n";
    }
}
```

Paginator 对象具有一种`search()`方法，可让您使用[JMESPath](guide_jmespath.md)表达式更轻松地从结果集中提取数据。

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

**注意**  
我们仍支持 `getIterator()` 方法，从而确保更顺畅地过渡到版本 3，但我们鼓励您迁移代码，以使用分页工具。

### 更改了许多高级抽象
<a name="many-higher-level-abstractions-have-changed"></a>

总体而言，我们改进或更新了许多高级抽象（除客户端之外，特定服务的帮助程序对象）。还删除了一些。
+   
**已更新：**  
  + [Amazon S3 分段上传](s3-multipart-upload.md)的使用方式已更改。Amazon Glacier 分段上传也进行了类似更改。
  + 创建[预签名的 Amazon S3](s3-presigned-url.md) 的方式 URLs已经改变。
  + `Aws\S3\Sync` 命名空间已替换为 `Aws\S3\Transfer` 类。`S3Client::uploadDirectory()` 和 `S3Client::downloadBucket()` 方法仍然可用，但有不同的选项。请参阅[适用于 PHP 的 AWS SDK 版本 3 的 Amazon S3 传输管理器的](s3-transfer.md)文档。
  +  `Aws\S3\Model\ClearBucket` 和 `Aws\S3\Model\DeleteObjectsBatch` 已替换为 `Aws\S3\BatchDelete` 和 `S3Client::deleteMatchingObjects()`。
  + 在[版本 3 中使用 DynamoDB 会话处理程序的选项和行为 适用于 PHP 的 AWS SDK 略有变化](service_dynamodb-session-handler.md)。
  + `Aws\DynamoDb\Model\BatchRequest` 命名空间已替换为 `Aws\DynamoDb\WriteRequestBatch`。请参阅 [DynamoDB WriteRequestBatch](https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.DynamoDb.WriteRequestBatch.html) 的文档。
  + `Aws\Ses\SesClient` 现可在使用 `SendRawEmail` 操作时处理对 `RawMessage` 的 base64 编码。
+   
**已删除：**  
  + Amazon DynamoDB`Item`、`Attribute` 和 `ItemIterator` 类 — 之前在[版本 2.7.0](https://github.com/aws/aws-sdk-php/blob/3.0.0/CHANGELOG.md#270===2014-10-08) 中已弃用。
  + Amazon SNS 消息验证程序 — 现在已成为[单独的轻量级项目](https://github.com/aws/aws-php-sns-message-validator)，不需要 SDK 作为依赖项。但此项目包含在开发工具包的 Phar 和 ZIP 分发版中。您可以在 [AWS PHP 开发博客上](https://aws.amazon.com/blogs/developer/receiving-amazon-sns-messages-in-php/)找到入门指南。
  + Amazon S3`AcpBuilder` 及其相关对象均已删除。

## 比较 SDK 这两个版本的代码示例
<a name="comparing-code-samples-from-both-versions-of-the-sdk"></a>

以下示例展示了 适用于 PHP 的 AWS SDK 版本 3 与版本 2 在使用方式上的一些不同之处。

### 示例：Amazon S3 `ListObjects` 操作
<a name="example-s3-listobjects-operation"></a>

#### SDK 版本 2
<a name="from-version-2-of-the-sdk"></a>

```
<?php

require '/path/to/vendor/autoload.php';

use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;

$s3 = S3Client::factory([
    'profile' => 'my-credential-profile',
    'region'  => 'us-east-1'
]);

try {
    $result = $s3->listObjects([
        'Bucket' => 'amzn-s3-demo-bucket',
        'Key'    => 'my-object-key'
    ]);

    foreach ($result['Contents'] as $object) {
        echo $object['Key'] . "\n";
    }
} catch (S3Exception $e) {
    echo $e->getMessage() . "\n";
}
```

#### SDK 版本 3
<a name="from-version-3-of-the-sdk"></a>

主要区别：
+ 使用 `new` 将客户端实例化，而不是 `factory()`。
+ 在实例化的过程中需要 `'version'` 和 `'region'` 选项。

```
<?php

require '/path/to/vendor/autoload.php';

use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;

$s3 = new S3Client([
    'profile' => 'my-credential-profile',
    'region'  => 'us-east-1',
    'version' => '2006-03-01'
]);

try {
    $result = $s3->listObjects([
        'Bucket' => 'amzn-s3-demo-bucket',
        'Key'    => 'my-object-key'
    ]);

    foreach ($result['Contents'] as $object) {
        echo $object['Key'] . "\n";
    }
} catch (S3Exception $e) {
    echo $e->getMessage() . "\n";
}
```

### 示例：实例化具有全局配置的客户端
<a name="example-instantiating-a-client-with-global-configuration"></a>

#### SDK 版本 2
<a name="id2"></a>

```
<?php return array(
    'includes' => array('_aws'),
    'services' => array(
        'default_settings' => array(
            'params' => array(
                'profile' => 'my_profile',
                'region'  => 'us-east-1'
            )
        ),
        'dynamodb' => array(
            'extends' => 'dynamodb',
            'params' => array(
                'region'  => 'us-west-2'
            )
        ),
    )
);
```

```
<?php

require '/path/to/vendor/autoload.php';

use Aws\Common\Aws;

$aws = Aws::factory('path/to/my/config.php');

$sqs = $aws->get('sqs');
// Note: SQS client will be configured for us-east-1.

$dynamodb = $aws->get('dynamodb');
// Note: DynamoDB client will be configured for us-west-2.
```

#### SDK 版本 3
<a name="id3"></a>

主要区别：
+ 使用 `Aws\Sdk` 类，而不是 `Aws\Common\Aws`。
+ 没有配置文件。使用一组配置。
+ 在实例化期间需要 `'version'` 选项。
+ 使用 `create<Service>()` 方法，而不是 `get('<service>')`。

```
<?php

require '/path/to/vendor/autoload.php';

$sdk = new Aws\Sdk([
    'profile' => 'my_profile',
    'region' => 'us-east-1',
    'version' => 'latest',
    'DynamoDb' => [
        'region' => 'us-west-2',
    ],
]);

$sqs = $sdk->createSqs();
// Note: Amazon SQS client will be configured for us-east-1.

$dynamodb = $sdk->createDynamoDb();
// Note: DynamoDB client will be configured for us-west-2.
```