处理AWS PHP SDK 2中的错误

Ben*_*air 7 amazon-s3 amazon-web-services

如果我试图从我的S3存储桶中获取一个不存在的对象,那么Amazon PHP SDK 2会给我一个非常难看的错误.方便我,但对最终用户没有任何意义......

例如:

$s3 = $aws->get('s3');

$result = $s3->getObject(array(
    'Bucket' => 'my bucket',
    'Key'    => 'path/to/file'
));
Run Code Online (Sandbox Code Playgroud)

错误:

致命错误:未捕获的Aws\S3\Exception\NoSuchKeyException:AWS错误代码:NoSuchKey,状态代码:404,AWS请求ID:xxxxxxxxxxxxx,AWS错误类型:客户端,AWS错误消息:指定的密钥不存在.在第89行的AWS/vendor/aws/aws-sdk-php/src/Aws/Common/Exception/NamespaceExceptionFactory.php中抛出

有没有办法可以确定是否存在错误并打印出有意义的消息而不是上述消息?

Ben*_*air 7

我突然想到尝试这个:

try {
    $result = $s3->getObject(array(
        'Bucket' => 'my bucket',
        'Key'    => 'path/to/file'
    ));
} catch (Exception $e) {
   // I can put a nicer error message here  
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ery 5

调用AWS SDK方法时发生的所有错误都通过抛出异常来指示.如果要处理错误,可以捕获这些异常.

在最简单的情况下,您可能只想捕获Exception:

try {
    $result = $s3->getObject(array(
        'Bucket' => 'my bucket',
        'Key'    => 'path/to/file'
    ));
}
catch (Exception $e) {
    echo 'Oops, something went wrong';
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您只想处理某些预期的异常,同时让其他人冒泡并使您的应用程序崩溃,那么事情会变得更加微妙.

首先,AWS命名空间中的几十个命名空间中的每一个都包含一个Exception命名空间,在该命名空间中定义了异常类.每个命名空间中的其中一个类是Amazon调用命名空间的默认服务异常类,所有其他异常都从该类继承.

例如,S3具有Aws\S3\Exception命名空间S3Exception.EC2具有Aws\Ec2\Exception命名空间Ec2Exception.

请注意,捕获其中一个异常而不是基Exception类会立即阻止我们捕获某些错误!由于服务器的错误响应而抛出特定于服务的异常; 连接失败异常不会从它们继承.例如,如果您尝试在没有互联网连接的情况下运行以下代码...

try {
    $result = $s3->getObject(array(
        'Bucket' => 'my bucket',
        'Key'    => 'path/to/file'
    ));
}
catch (S3Exception $e) {
    echo 'Oops, something went wrong';
}
Run Code Online (Sandbox Code Playgroud)

...然后异常将不被捕获(因为它将是一个Guzzle\Http\Exception\CurlException,而不是S3Exception)并且程序将崩溃.出于这个原因,如果您只是为了向用户提供通用失败消息而捕获这些异常,那么您应该抓住它们Exception.

让我们回到如何处理特定错误的问题.对于大多数命名空间,答案是会为该错误定义一个异常类,你应该抓住它.例如,假设我们再次使用S3 getObject方法,并且想要在我们要求的存储桶不存在时执行某些操作.查看S3 Exception命名空间文档,我们看到有一个NoSuchBucketException我们可以捕获:

try {
    $result = $s3->getObject(array(
        'Bucket' => 'my bucket',
        'Key'    => 'path/to/file'
    ));
}
catch (NoSuchBucketException $e) {
    echo 'There is no such bucket.';
}
Run Code Online (Sandbox Code Playgroud)

(在实践中,通过试验和错误的操作可能比通过仔细阅读文档更容易确定哪些操作可以引发异常.)

最后,值得一提的是EC2 API.与所有其他服务不同,EC2名称空间仅包含一个异常类,即Ec2Exception.如果要捕获并处理特定错误,则需要检查异常对象以确定您正在处理的错误类型.您可以通过检查getExceptionCode()异常方法返回的值来执行此操作.

例如,我最近编写的脚本中的(修改过的)片段授予指定的IP访问我们的MySQL服务器:

try {
    $result = $ec2->authorizeSecurityGroupIngress([
        'GroupName' => 'mygroup',
        'IpProtocol' => 'tcp',
        'ToPort' => 3306,
        'CidrIp' => $ip . "/32",
    ]);
}
catch (Ec2Exception $e) {
    if ($e->getExceptionCode() == 'InvalidPermission.Duplicate') {
        echo "IP already has requested permission.";
    }
    else {
        // Don't know how to deal with this error; let's crash
        throw $e;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,InvalidPermission.DuplicateAWS PHP SDK文档中未列出可能的异常代码(如本例所示),但您可以通过反复试验或EC2 API本身文档找到它们,其中每个API操作的页面都包含'错误部分列出了它可以返回的错误代码.