応答モデル

はじめに

コマンドの結果は Model (Guzzle\Service\Resource\Model) オブジェクトです。 このオブジェクトは、レスポンスボディからの結果を含み、配列 (例 $result['TableName']) として利用することができます。 また、このオブジェクトは get()getPath()toArray() のようなメソッドを利用することができます。 レスポンスモデルの内容は、実行され API docs に記述されたそれぞれの操作コマンドによります。 (例 S3 GetObject operation の API docs の Returns セクションをご参照ください。

// Use an instance of S3Client to get an object
$result = $client->getObject(array(
    'Bucket' => 'my-bucket',
    'Key'    => 'test.txt'
));

// Introspect the keys
var_export($result->getKeys());
//> array( 'Body', 'ContentLength', 'DeleteMarker', 'Expiration', ... )

// Get a value
echo $result['ContentLength'];
// OR
echo $result->get('ContentLength');
//> 6

// Get a nested value
echo $result->getPath('Metadata/CustomValue');
//> Testing123

// Get an array of the data
var_export($result->toArray());
//> array ( 'Body' => 'Hello!' , 'ContentLength' => 6, ... )

Modelオブジェクトの操作

Modelオブジェクト (およびCommandオブジェクト) は Guzzle Collectionクラス を継承し、 ArrayAccessIteratorAggregateCountable というPHPネイティブの各インタフェイスを実装しています。 したがって、キーにアクセスし、キーと値の組について反復する場合、配列のように振る舞います。 また、Modelオブジェクトの toArray() メソッドを使えば、配列の形で直接取得することも可能です。

但し、未定義のキーでアクセスしても例外が発生しないので、 isset() で確認せず、値を直接参照しても安全です。 キーが未定義ならば値は null になります。

// Using a value that may not exist
if (!$result['ContentLength']) {
    echo "Empty file.";
}

$isDeleted = (bool) $result->get('DeleteMarker');

もちろん、 Model には ArrayAccess が実装されているので、従来通り isset() を使っても構いません。 Modelオブジェクト (およびその基盤であるCollectionオブジェクト) には、 キーと値を検索、確認する便宜メソッドもあります。

// You can use isset() since the object implements ArrayAccess
if (!isset($result['ContentLength'])) {
    echo "Empty file.";
}

// There is also a method that does the same type of check
if (!$result->hasKey('ContentLength')) {
    echo "Empty file.";
}

// If needed, you can search for a key in a case-insensitive manner
echo $result->keySearch('body');
//> Body
echo $result->keySearch('Body');
//> Body

// You can also list all of the keys in the result
var_export($result->getKeys());
//> array ( 'Body', 'DeleteMarker', 'Expiration', 'ContentLength', ... )

// The getAll() method will return the result data as an array
// You can specify a set of keys to only get a subset of the data
var_export($result->getAll(array('Body', 'ContentLength')));
//> array ( 'Body' => 'Hello!' , 'ContentLength' => 6 )

入れ子になった値の取得

モデルの getPath() メソッドを使えば、入れ子になった値を応答から容易に取得できて便利です。 パスは一連のキーをスラッシュで区切って表します。

// Perform a RunInstances operation and traverse into the results to get the InstanceId
$result = $ec2Client->runInstances(array(
    'ImageId'      => 'ami-548f13d',
    'MinCount'     => 1,
    'MaxCount'     => 1,
    'InstanceType' => 't1.micro',
));
$instanceId = $result->getPath('Instances/0/InstanceId');

ワイルドカードを使い、データ配列の形で複数の値を取得することも可能です。 上記の例を修正し、複数のInstanceIdを検索できるようにした例を示します。

// Perform a RunInstances operation and get an array of the InstanceIds that were created
$result = $ec2Client->runInstances(array(
    'ImageId'      => 'ami-548f13d',
    'MinCount'     => 3,
    'MaxCount'     => 5,
    'InstanceType' => 't1.micro',
));
$instanceId = $result->getPath('Instances/*/InstanceId');

モデルに保持されているデータの参照

応答モデルにはサービスオペレーションからの応答をパースしたデータも格納されているので、 モデルの中身は実行したオペレーションによって異なります。

オペレーションに応じ、モデルオブジェクトにどのようなデータが保持されているのかを調べるためには、SDKに付属のAPI資料が役に立つでしょう。 各オペレーション (S3 GetObjectオペレーションEC2 RunInstancesオペレーション など) の 「 Returns 」節に、応答モデルが保持するデータの完全な仕様が載っています。

toArray() メソッドを使えば、応答モデルを直接、配列に変換できます。 デバッグの際には、 toArray()print_r() を組み合わせて、応答データを表示してみることも可能です。

$result = $ec2Client->runInstances(array(/* ... */));
print_r($result->toArray());

また、サービス記述を調べることも可能です。これはクライアントの名前空間ディレクトリ以下、 Resources ディレクトリにあります。 SQSのサービス記述 (src/Aws/Sqs/Resources/ 以下) を調べた結果 (一部) を以下に示します。 これは SendMessage オペレーションの応答に関するスキーマです。

'SendMessageResult' => array(
    'type' => 'object',
    'additionalProperties' => true,
    'properties' => array(
        'MD5OfMessageBody' => array(
            'description' => 'An MD5 digest of the non-URL-encoded message body string. This can be used to verify that SQS received the message correctly. SQS first URL decodes the message before creating the MD5 digest. For information about MD5, go to http://faqs.org/rfcs/rfc1321.html.',
            'type' => 'string',
            'location' => 'xml',
        ),
        'MessageId' => array(
            'description' => 'The message ID of the message added to the queue.',
            'type' => 'string',
            'location' => 'xml',
        ),
    ),
),

最後に、Guzzleやそのサービス記述クラスを使い慣れているならば、 $result->getStructure() を呼び出すことにより、 モデルオブジェクトからパラメータ構造体を取得できます (API資料のうちgetStructureメソッドに関する項 を参照)。

応答ヘッダの取得

Response オブジェクトに、 Model オブジェクトから直接アクセスすることはできません。 ヘッダ値や状態コードなどのデータを応答から取得するためには、 Response オブジェクトを Command オブジェクトから取得しておく必要があります (『 Quick Start 』ガイドの コマンドの実行 を参照)。 コマンドオブジェクトに直接アクセスできるよう、簡易コマンド構文から拡張構文に切り替えなければならないかも知れません。

// Getting the response Model with the shorthand syntax
$result = $s3Client->createBucket(array(/* ... */));

// Getting the response Model with the expanded syntax
$command = $s3Client->getCommand('CreateBucket', array(/* ... */));
$result = $command->getResult();

// Getting the Response object from the Command
$response = $command->getResponse();
$response->getHeader('Content-Length');
$response->getStatusCode();

Amazon S3やAmazon GlacierなどREST風のサービスでは特にそうですが、 最も重要なヘッダは初めから応答モデルに入っていることもあります。