File: feature-commands.rst

package info (click to toggle)
aws-sdk-for-php 2.7.2-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 14,448 kB
  • ctags: 10,879
  • sloc: php: 157,235; python: 233; makefile: 184; xml: 28; sh: 5
file content (204 lines) | stat: -rw-r--r-- 7,844 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
===============
Command Objects
===============

Command objects are fundamental to how the SDK works. In normal usage of the SDK, you may never interact with command
objects. However, if you are :ref:`performing operations in parallel <parallel_commands>`,
:ref:`inspecting data from the request or response <requests_and_responses>`, or writing custom plugins, you will need
to understand how they work.

Typical SDK usage
-----------------

.. include:: _snippets/performing-operations.txt

A peek under the hood
---------------------

If you examine a client class, you will see that the methods corresponding to the operations do not actually exist. They
are implemented using the ``__call()`` magic method behavior. These pseudo-methods are actually shortcuts that
encapsulate the SDK's — and the underlying Guzzle library's — use of command objects.

For example, you could perform the same ``DescribeTable`` operation from the preceding section using command objects:

.. code-block:: php

    $command = $dynamoDbClient->getCommand('DescribeTable', array(
        'TableName' => 'YourTableName',
    ));
    $result = $command->getResult();

A **Command** is an object that represents the execution of a service operation. Command objects are an abstraction of
the process of formatting a request to a service, executing the request, receiving the response, and formatting the
results. Commands are created and executed by the client and contain references to **Request** and **Response** objects.
The **Result** object is a what we refer to as a :doc:`"modeled response" <feature-models>`.

Using command objects
---------------------

Using the pseudo-methods for performing operations is shorter and preferred for typical use cases, but command objects
provide greater flexibility and access to additional data.

Manipulating command objects before execution
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When you create a command using a client's ``getCommand()`` method, it does not immediately execute. Because commands
are lazily executed, it is possible to pass the command object around and add or modify the parameters. The following
examples show how to work with command objects:

.. code-block:: php

    // You can add parameters after instantiation
    $command = $s3Client->getCommand('ListObjects');
    $command->set('MaxKeys', 50);
    $command->set('Prefix', 'foo/baz/');
    $result = $command->getResult();

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

    // The set method is chainable
    $result = $s3Client->getCommand('ListObjects')
        ->set('MaxKeys', 50);
        ->set('Prefix', 'foo/baz/');
        ->getResult();

    // You can also use array access
    $command = $s3Client->getCommand('ListObjects');
    $command['MaxKeys'] = 50;
    $command['Prefix'] = 'foo/baz/';
    $result = $command->getResult();

Also, see the `API docs for commands
<http://docs.aws.amazon.com/aws-sdk-php/latest/class-Guzzle.Service.Command.AbstractCommand.html>`_.

.. _requests_and_responses:

Request and response objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

From the command object, you can access the request, response, and result objects. The availability of these objects
depend on the state of the command object.

Managing command state
^^^^^^^^^^^^^^^^^^^^^^

Commands must be prepared before the request object is available, and commands must executed before the response and
result objects are available.

.. code-block:: php

    // 1. Create
    $command = $client->getCommand('OperationName');

    // 2. Prepare
    $command->prepare();
    $request = $command->getRequest();
    // Note: `prepare()` also returns the request object

    // 3. Execute
    $command->execute();
    $response = $command->getResponse();
    $result = $command->getResult();
    // Note: `execute()` also returns the result object

This is nice, because it gives you a chance to modify the request before it is actually sent.

.. code-block:: php

    $command = $client->getCommand('OperationName');
    $request = $command->prepare();
    $request->addHeader('foo', 'bar');
    $result = $command->execute();

You don't have to manage each aspect of the state though, calling ``execute()`` will also prepare the command, and
calling ``getResult()`` will prepare and execute the command.

Using requests and responses
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Request and response objects contain data about the actual requests and responses to the service.

.. code-block:: php

    $command = $client->getCommand('OperationName');
    $command->execute();

    // Get and use the request object
    $request = $command->getRequest();
    $contentLength = $request->getHeader('Content-Length');
    $url = $request->getUrl();

    // Get and use the response object
    $response = $command->getResponse();
    $success = $response->isSuccessful();
    $status = $response->getStatusCode();

You can also take advantage of the ``__toString`` behavior of the request and response objects. If you print them
(e.g., ``echo $request;``), you can see the raw request and response data that was sent over the wire.

To learn more, read the API docs for the `Request
<http://docs.aws.amazon.com/aws-sdk-php/latest/class-Guzzle.Http.Message.Request.html>`_ and `Response
<http://docs.aws.amazon.com/aws-sdk-php/latest/class-Guzzle.Http.Message.Response.html>`_ classes.

.. _parallel_commands:

Executing commands in parallel
------------------------------

The AWS SDK for PHP allows you to execute multiple operations in parallel when you use command objects. This can reduce
the total time (sometimes drastically) it takes to perform a set of operations, since you can do them at the same time
instead of one after another. The following shows an example of how you could upload two files to Amazon S3 at the same
time.

.. code-block:: php

    $commands = array();
    $commands[] = $s3Client->getCommand('PutObject', array(
        'Bucket' => 'SOME_BUCKET',
        'Key'    => 'photos/photo01.jpg',
        'Body'   => fopen('/tmp/photo01.jpg', 'r'),
    ));
    $commands[] = $s3Client->getCommand('PutObject', array(
        'Bucket' => 'SOME_BUCKET',
        'Key'    => 'photos/photo02.jpg',
        'Body'   => fopen('/tmp/photo02.jpg', 'r'),
    ));

    // Execute an array of command objects to do them in parallel
    $s3Client->execute($commands);

    // Loop over the commands, which have now all been executed
    foreach ($commands as $command) {
        $result = $command->getResult();
        // Do something with result
    }

Error handling with parallel commands
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When executing commands in parallel, error handling becomes a bit trickier. If an exception is thrown, then the SDK (via
Guzzle) will aggregate the exceptions together and throw a single ``Guzzle\Service\Exception\CommandTransferException``
(`see the API docs
<http://docs.aws.amazon.com/aws-sdk-php/latest/class-Guzzle.Service.Exception.CommandTransferException.html>`_) once all
of the commands have completed execution. This exception class keeps track of which commands succeeded and which failed
and also allows you to fetch the original exceptions thrown for failed commands.

.. code-block:: php

    use Guzzle\Service\Exception\CommandTransferException;

    try {
        $succeeded = $client->execute($commands);
    } catch (CommandTransferException $e) {
        $succeeded = $e->getSuccessfulCommands();
        echo "Failed Commands:\n";
        foreach ($e->getFailedCommands() as $failedCommand) {
            echo $e->getExceptionForFailedCommand($failedCommand)->getMessage() . "\n";
        }
    }