AWS SDK for PHP バージョン 3 のコマンドオブジェクト - AWS SDK for PHP

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

AWS SDK for PHP バージョン 3 のコマンドオブジェクト

AWS SDK for PHP は、コマンドパターンを使用して、後でHTTPリクエストを転送するために使用されるパラメータとハンドラーをカプセル化します。

コマンドの暗黙的な使用

クライアントクラスを調べると、APIオペレーションに対応するメソッドが実際に存在しないことがわかります。これらは __call() マジックメソッドを使用して実装されます。これらの擬似メソッドは、実際には SDKによるコマンドオブジェクトの使用をカプセル化するショートカットです。

通常、コマンドオブジェクトを直接操作する必要はありません。のようなメソッドを呼び出すとAws\S3\S3Client::putObject()、 は実際に指定されたパラメータに基づいてAws\CommandInterfaceオブジェクトSDKを作成し、コマンドを実行し、入力されたAws\ResultInterfaceオブジェクトを返します (またはエラーに対して例外をスローします)。同様のフローは、クライアントのいずれかのAsyncメソッド (例: Aws\S3\S3Client::putObjectAsync()) を呼び出すときに発生します。クライアントは、提供されたパラメータに基づいてコマンドを作成し、HTTPリクエストをシリアル化し、リクエストを開始し、プロミスを返します。

以下の例も機能的に同様です。

$s3Client = new Aws\S3\S3Client([ 'version' => '2006-03-01', 'region' => 'us-standard' ]); $params = [ 'Bucket' => 'foo', 'Key' => 'baz', 'Body' => 'bar' ]; // Using operation methods creates a command implicitly $result = $s3Client->putObject($params); // Using commands explicitly $command = $s3Client->getCommand('PutObject', $params); $result = $s3Client->execute($command);

コマンドのパラメーター

すべてのコマンドは、サービスの の一部ではなくAPI、代わりに SDKの動作を制御するいくつかの特別なパラメータをサポートしています。

@http

このパラメータを使用すると、基になるHTTPハンドラーがリクエストを実行する方法を微調整できます。@http パラメータに含めることができるオプションは、「http」クライアントオプションを使用してそのクライアントをインスタンス化するときに設定できるオプションと同じです。

// Configures the command to be delayed by 500 milliseconds $command['@http'] = [ 'delay' => 500, ];

@retries

「retries」クライアントオプションと同様に、@retries は、コマンドが失敗したと見なされるまでに再試行できる回数を制御します。再試行を無効にするには、0 に設定します。

// Disable retries $command['@retries'] = 0;
注記

クライアントで再試行を無効にしている場合は、そのクライアントに渡される個別のコマンドで再試行を選択的に有効にすることはできません。

コマンドオブジェクトの作成

クライアントの getCommand() メソッドを使用してコマンドを作成することができます。HTTP リクエストはすぐに実行または転送されませんが、クライアントの execute() メソッドに渡された場合にのみ実行されます。これにより、コマンドを実行する前にコマンドオブジェクトを変更する機会が得られます。

$command = $s3Client->getCommand('ListObjects'); $command['MaxKeys'] = 50; $command['Prefix'] = 'foo/baz/'; $result = $s3Client->execute($command); // You can also modify parameters $command = $s3Client->getCommand('ListObjects', [ 'MaxKeys' => 50, 'Prefix' => 'foo/baz/', ]); $command['MaxKeys'] = 100; $result = $s3Client->execute($command);

コマンド

コマンドがクライアントから作成された場合、クライアントの Aws\HandlerList オブジェクトのクローンが与えられます。コマンドは、クライアントのハンドラーリストのクローンとして与えられ、クライアントが実行する他のコマンドに影響しない、カスタムミドルウェアとハンドラーを使用するためにコマンドが許可されます。

つまり、コマンドごとに異なるHTTPクライアント (例: Aws\MockHandler) を使用し、ミドルウェアを介してコマンドごとにカスタム動作を追加できます。次の例ではMockHandler、 を使用して、実際のHTTPリクエストを送信する代わりにモック結果を作成します。

use Aws\Result; use Aws\MockHandler; // Create a mock handler $mock = new MockHandler(); // Enqueue a mock result to the handler $mock->append(new Result(['foo' => 'bar'])); // Create a "ListObjects" command $command = $s3Client->getCommand('ListObjects'); // Associate the mock handler with the command $command->getHandlerList()->setHandler($mock); // Executing the command will use the mock handler, which returns the // mocked result object $result = $client->execute($command); echo $result['foo']; // Outputs 'bar'

コマンドを使用するハンドラーの変更に加えて、カスタムミドルウェアをコマンドに挿入することもできます。次の例では、ハンドラーリストでオブザーバーとして機能する tap ミドルウェアを使用します。

use Aws\CommandInterface; use Aws\Middleware; use Psr\Http\Message\RequestInterface; $command = $s3Client->getCommand('ListObjects'); $list = $command->getHandlerList(); // Create a middleware that just dumps the command and request that is // about to be sent $middleware = Middleware::tap( function (CommandInterface $command, RequestInterface $request) { var_dump($command->toArray()); var_dump($request); } ); // Append the middleware to the "sign" step of the handler list. The sign // step is the last step before transferring an HTTP request. $list->append('sign', $middleware); // Now transfer the command and see the var_dump data $s3Client->execute($command);

CommandPool

Aws\CommandPool オブジェクトを生成するイテレーターを使用して、Aws\CommandInterface により、コマンドを同時に実行できます。CommandPool は、プール内のコマンドを繰り返し実行する (コマンドが完了時に、固定プールサイズを確保するために複数実行される) 間に、一定数のコマンドが同時に実行されるようにします。

ここでは、CommandPool を使用し、いくつかのコマンドを送信するだけの非常に簡単な例を示します。

use Aws\S3\S3Client; use Aws\CommandPool; // Create the client $client = new S3Client([ 'region' => 'us-standard', 'version' => '2006-03-01' ]); $bucket = 'example'; $commands = [ $client->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => 'a']), $client->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => 'b']), $client->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => 'c']) ]; $pool = new CommandPool($client, $commands); // Initiate the pool transfers $promise = $pool->promise(); // Force the pool to complete synchronously $promise->wait();

この例では CommandPool のごく一部の機能しか利用していません。より複雑な例を試してみましょう。例えば、ディスク上のファイルを Amazon S3 バケットにアップロードするとします。ディスクからファイルのリストを取得するには、 PHPの を使用できますDirectoryIterator。このイテレーターにより SplFileInfo オブジェクトが生成されます。CommandPoolAws\CommandInterface オブジェクトを生成するイテレーターを受け入れます。そのため、SplFileInfo オブジェクトにマッピングして Aws\CommandInterface オブジェクトを返します。

<?php require 'vendor/autoload.php'; use Aws\Exception\AwsException; use Aws\S3\S3Client; use Aws\CommandPool; use Aws\CommandInterface; use Aws\ResultInterface; use GuzzleHttp\Promise\PromiseInterface; // Create the client $client = new S3Client([ 'region' => 'us-standard', 'version' => '2006-03-01' ]); $fromDir = '/path/to/dir'; $toBucket = 'amzn-s3-demo-bucket'; // Create an iterator that yields files from a directory $files = new DirectoryIterator($fromDir); // Create a generator that converts the SplFileInfo objects into // Aws\CommandInterface objects. This generator accepts the iterator that // yields files and the name of the bucket to upload the files to. $commandGenerator = function (\Iterator $files, $bucket) use ($client) { foreach ($files as $file) { // Skip "." and ".." files if ($file->isDot()) { continue; } $filename = $file->getPath() . '/' . $file->getFilename(); // Yield a command that is executed by the pool yield $client->getCommand('PutObject', [ 'Bucket' => $bucket, 'Key' => $file->getBaseName(), 'Body' => fopen($filename, 'r') ]); } }; // Now create the generator using the files iterator $commands = $commandGenerator($files, $toBucket); // Create a pool and provide an optional array of configuration $pool = new CommandPool($client, $commands, [ // Only send 5 files at a time (this is set to 25 by default) 'concurrency' => 5, // Invoke this function before executing each command 'before' => function (CommandInterface $cmd, $iterKey) { echo "About to send {$iterKey}: " . print_r($cmd->toArray(), true) . "\n"; }, // Invoke this function for each successful transfer 'fulfilled' => function ( ResultInterface $result, $iterKey, PromiseInterface $aggregatePromise ) { echo "Completed {$iterKey}: {$result}\n"; }, // Invoke this function for each failed transfer 'rejected' => function ( AwsException $reason, $iterKey, PromiseInterface $aggregatePromise ) { echo "Failed {$iterKey}: {$reason}\n"; }, ]); // Initiate the pool transfers $promise = $pool->promise(); // Force the pool to complete synchronously $promise->wait(); // Or you can chain the calls off of the pool $promise->then(function() { echo "Done\n"; });

CommandPool の設定

Aws\CommandPool コンストラクタはさまざまな設定オプションを受け入れます。

concurrency (callable|int)

同時に実行するコマンドの最大数。プールを動的にサイズ変更する関数を提供します。この関数は、現在保留中のリクエスト数を取得し、新しいプールのサイズ制限を表す整数を返します。

before (callable)

各コマンドを送信する前に呼び出す関数。この before 関数では、コマンドとコマンドのイテレーターのキーを受け付けます。コマンドを送信する前に、before 関数で、必要に応じてコマンドを変更できます。

fulfilled (callable)

promise が実行されたときに呼び出す関数。この関数は、プールを省略する必要がある場合、解決または拒否できる集計 promise と結果の基になるイテレーターの ID、結果オブジェクトが提供されます。

rejected (callable)

promise が拒否されたときに呼び出す関数。この関数は、プールを省略する必要がある場合、解決または拒否できる集計 promise と例外の基になるイテレーターの ID、Aws\Exception オブジェクトが提供されます。

コマンド間の手動のガベージコレクション

大きなコマンドプールでメモリ制限に達している場合、メモリ制限に達したときにPHPガベージコレクターによってまだ収集SDKされていない によって生成された循環参照が原因である可能性があります。コマンド間で収集アルゴリズムを手動で呼び出すと、制限に達する前にサイクルを収集できます。次の例では、各コマンドを送信する前にコールバックを使用して収集アルゴリズムを呼び出す CommandPool を作成します。ガベージコレクターを呼び出してもパフォーマンスに影響することはなく、最適な使用はお客様のユースケースと環境によって異なることに注意してください。

$pool = new CommandPool($client, $commands, [ 'concurrency' => 25, 'before' => function (CommandInterface $cmd, $iterKey) { gc_collect_cycles(); } ]);