PHP – AWS Developer Blog https://aws.amazon.com/blogs/developer/ Thu, 07 Sep 2017 17:51:10 +0000 en-US hourly 1 Automated Changelog in AWS SDK for PHP https://aws.amazon.com/blogs/developer/automated-changelog-in-php-sdk-for-aws/ Thu, 31 Aug 2017 20:35:12 +0000 b458b8a583b8b847d0a0c0bd6003bde52aae8285 Starting with version 3.22.10 of the AWS SDK for PHP, released February 23, 2017, the Changelog Builder automatically processes all changelog entries. Each pull request is required to have a changelog JSON blob as part of the request. The system also calculates&nbsp;the next version for the SDK based on the type of the changes that […] <p>Starting with version 3.22.10 of the <a title="undefined" href="https://github.com/aws/aws-sdk-php" target="_blank" rel="noopener noreferrer">AWS SDK for PHP</a>, released February 23, 2017, the Changelog Builder automatically processes all changelog entries. Each pull request is required to have a changelog JSON blob as part of the request. The system also calculates&nbsp;the next version for the SDK based on the type of the changes that are defined in the given changelog JSON blob.</p> <p>The update simplifies the process of adding release notes to the&nbsp;<a title="undefined" href="https://github.com/aws/aws-sdk-php/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer">CHANGELOG.md</a>&nbsp;file for each pull request. Each merged pull request that was part of the release results in a new entry to the CHANGELOG.md file. The entry describes the change and provides the TAG number and release date.</p> <p>The following is a sample changelog blob.</p> <pre><code class="lang-js">[ { &quot;type&quot; : &quot;feature|enhancement|bugfix&quot;, &quot;category&quot; : &quot;Target of Update&quot;, &quot;description&quot;: &quot;English language simple description of your update.&quot; } ] </code></pre> <p>Each changelog blob is required to define the&nbsp;“type”,&nbsp;“category”,&nbsp;and&nbsp;“description” fields. The “category” explains the service that the change is associated with. For SDK changes that are not related to any service, the category field is left as an empty string. The “description” field should contain one or two sentences detailing the changes.</p> <p>The “type” field describes the scope of the change being proposed. This field helps the Changelog Builder decide if a minor version bump is needed. The “type” field is assigned one of the following values:</p> <ol> <li><strong>feature:</strong> A major change to the SDK that will cause a minor version bump. A feature will open a new use case or significantly improve upon an existing one. The update will result in a minor version bump. Example: a new AWS service.</li> <li><strong>enhancement:</strong> A small update to the code. This should not cause any code to break and should only enhance given functionality of the SDK. The update will result in a patch version update. Example: Documentation Update.</li> <li><strong>bugfix:</strong> A fix in the code that has caused some unwanted behavior. The update will result in a patch version update.</li> </ol> <p>The changelog blob&nbsp;that will be included in the next release must be put inside the .changes/nextrelease folder. The changelog blob file name must be unique in that folder. A good practice is to give a descriptive name to the changelog blob file related to the request.</p> <p>On each release, the SDK looks inside the .changes/nextrelease folder and consolidates all JSON&nbsp;blobs into a single JSON&nbsp;document. Then the SDK calculates the next version number, based on the full JSON document.</p> <p><strong>Example:</strong></p> <p><strong>Current SDK Version:</strong> 1.2.3<br /> <span style="text-decoration: underline">Changelog Blob File 1:</span> update-s3-client.json</p> <pre><code class="lang-js">[ { &quot;type&quot; : &quot;enhancement&quot;, &quot;category&quot; : &quot;S3&quot;, &quot;description&quot;: &quot;Adds support for new feature in s3&quot; } ]</code></pre> <p><span style="text-decoration: underline">Changelog Blob File 2:</span> ec2-documentation-update.json</p> <pre><code class="lang-js">[ { &quot;type&quot; : &quot;enhancement&quot;, &quot;category&quot; : &quot;EC2&quot;, &quot;description&quot;: &quot;Update Ec2 documentation for operation foo bar&quot; } ]</code></pre> <p><span style="text-decoration: underline">Changelog Blob File 3:</span> sdk-bugfix.json</p> <pre><code class="lang-js">[ { &quot;type&quot; : &quot;bugfix&quot;, &quot;category&quot; : &quot;&quot;, &quot;description&quot;: &quot;Fixes a typo in Aws Client&quot; } ]</code></pre> <p><strong>Consolidated JSON document:</strong> .changes/1.2.4.json<br /> <span style="text-decoration: underline">Next SDK version:</span> 1.2.4</p> <pre><code class="lang-js">[ { &quot;type&quot;: &quot;enhancement&quot;, &quot;category&quot;: &quot;S3&quot;, &quot;description&quot;: &quot;Adds support for new feature in s3&quot; }, { &quot;type&quot;: &quot;enhancement&quot;, &quot;category&quot;: &quot;EC2&quot;, &quot;description&quot;: &quot;Update Ec2 documentation for operation foo bar&quot; }, { &quot;type&quot;: &quot;bugfix&quot;, &quot;category&quot;: &quot;&quot;, &quot;description&quot;: &quot;Fixes a typo in Aws Client&quot; } ]</code></pre> <p>A new file, with the name VERSION_NUMBER.json, will be created in the .changes folder with the contents of the JSON&nbsp;blob for the changelog. You can see the previous changelog JSON blobs&nbsp;here. If needed, we can reconstruct the CHANGELOG.md file using the JSON&nbsp;documents in the .changes folder.</p> <p>On a successful release, the changelog entries are written to the top of the CHANGELOG.md file. Then&nbsp;chag&nbsp;is used to tag the SDK and label the added release notes with the current version number.</p> <p>For more information about Changelog Builder, see <a title="ChangelogBuilder.php class" href="https://github.com/aws/aws-sdk-php/blob/master/build/changelog/ChangelogBuilder.php" target="_blank" rel="noopener noreferrer">Class Aws\Build\ChangelogBuilder</a> and <a title="CONTRIBUTING.md" href="https://github.com/aws/aws-sdk-php/blob/master/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer">CONTRIBUTING.md</a>.</p> PHP application logging with Amazon CloudWatch Logs and Monolog https://aws.amazon.com/blogs/developer/php-application-logging-with-amazon-cloudwatch-logs-and-monolog/ Fri, 21 Apr 2017 19:28:59 +0000 92b49b5a700e0fbaf03281e85fbe2e04c0cb74e5 Logging and information debugging can be approached from a multitude of different angles. Whether you use an application framework or coding from scratch it’s always comforting to have familiar components and tools across different projects. In our examples today, I am going to enable Amazon CloudWatch Logs logging with a PHP application. To accomplish this, […] <p>Logging and information debugging can be approached from a multitude of different angles. Whether you use an application framework or coding from scratch it’s always comforting to have familiar components and tools across different projects. In our examples today, I am going to enable <a href="http://aws.amazon.com/cloudwatch" target="_blank">Amazon CloudWatch Logs</a> logging with a PHP application. To accomplish this, I wanted to use an existing solution that is both already popular and well used, and that is standards compliant. For these reasons, we are going to use the open source log library, PHP Monolog (<a href="https://github.com/Seldaek/monolog" target="_blank">https://github.com/Seldaek/monolog</a>).</p> <p><strong>PHP Monolog</strong></p> <p>For those who work with a new PHP application, framework, or service, one of the technology choices that appears more frequently across solutions is the use of Monolog for application logging. PHP Monolog is a standards-compliant PHP library that enables developers to send logs to various destination types including, databases, files, sockets, and different services. Although PHP Monolog predates the standards for PHP logging defined in <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md" target="_blank">PSR-3</a>, it does implement the PSR-3 interface and standards. This makes Monolog compliant with the common interface for logging libraries. Using Monolog with CloudWatch Logs creates a PSR-3 compatible logging solution. Monolog is available for use with a number of different applications and frameworks such as Laravel, Symfony, CakePHP, and many others. Our example today is about using PHP Monolog to send information to CloudWatch Logs for the purpose of application logging and to build a structure and process that enables the use of our application data with CloudWatch alarms and notifications. This enables us to use logs from our application for cross-service actions such as with <a href="http://aws.amazon.com/ec2" target="_blank">Amazon EC2 </a><a href="https://aws.amazon.com/autoscaling/" target="_blank">Auto Scaling decisions</a>.</p> <p><strong>Amazon CloudWatch Logs</strong></p> <p>As a customer-driven organization, AWS is constantly building and releasing significant features and services requested by AWS customers and partners. One of those services that we highlight today is Amazon CloudWatch Logs. CloudWatch Logs enables you to store log file information from applications, operating systems and instances, AWS services, and various other sources. <a href="https://aws.amazon.com/blogs/aws/cloudwatch-log-service/" target="_blank">An earlier blog post</a> highlighted the use of CloudWatch Logs with various programming examples.</p> <p>Notice in the blog post that there is a PHP example that uses CloudWatch Logs to store an entry from an application. You can use this example and extend it as a standalone solution to provide logging to CloudWatch Logs from within your application. With our examples, we’ll enhance this opportunity by leveraging PHP Monolog.</p> <p><strong>Implementing Monolog</strong></p> <p>To begin using Monolog, we install the necessary libraries with the use of Composer (<a href="https://getcomposer.org/" target="_blank">https://getcomposer.org/</a>). The instructions below install the <a href="https://aws.amazon.com/sdk-for-php/" target="_blank">AWS SDK for PHP</a>, PHP Monolog, and an <a href="https://github.com/maxbanton/cwh" target="_blank">add-on to Monolog that enables logging to CloudWatch Logs</a>.</p> <pre><code class="lang-bash">curl -sS https://getcomposer.org/installer | php php composer.phar require aws/aws-sdk-php php composer.phar require monolog/monolog php composer.phar require maxbanton/cwh:^1.0 </code></pre> <p><a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-09.png" target="_blank"><img style="width: 640px;height: 326px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-09-1024x521.png" alt="" width="640" height="326" /></a></p> <p><a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-10.png" target="_blank"><img style="width: 640px;height: 449px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-10.png" alt="" width="640" height="449" /></a></p> <p>Alternatively, you can copy the following entry to the composer.json file and install it via the <em>php composer.phar install</em> command.</p> <pre><code class="lang-javascript">{ &quot;minimum-stability&quot;: &quot;stable&quot;, &quot;require&quot;: { &quot;aws/aws-sdk-php&quot;: &quot;^3.24&quot;, &quot;aws/aws-php-sns-message-validator&quot;: &quot;^1.1&quot;, &quot;monolog/monolog&quot;: &quot;^1.21&quot;, &quot;maxbanton/cwh&quot;: &quot;^1.0&quot; } }</code></pre> <p><strong>Local logging</strong></p> <p>Now that PHP Monolog is available for use, we can test the implementation. We start with an example of logging to a single file.</p> <pre><code class="lang-php">require &quot;vendor/autoload.php&quot;; use Monolog\Logger; use Monolog\Formatter\LineFormatter; use Monolog\Handler\StreamHandler; $logFile = &quot;testapp_local.log&quot;; $logger = new Logger('TestApp01'); $formatter = new LineFormatter(null, null, false, true); $infoHandler = new StreamHandler(__DIR__.&quot;/&quot;.$logFile, Logger::INFO); $infoHandler-&gt;setFormatter($formatter); $logger-&gt;pushHandler($infoHandler); $logger-&gt;info('Initial test of application logging.');</code></pre> <p>In the previous example, we start by requiring the composer libraries we installed earlier. The <em>new Logger</em> line sets the channel name as “TestApp01”. The next line creates a new LineFormatter that removes brackets around unused log items. The next line establishes the destination as the file name we identified, <em>testapp_local.log</em>, and associates that with the INFO log level. Next, we apply the format to our stream handler. Then we add the stream handler with the updated format to the handler list. Finally, a new message is logged with the log level of INFO. For information about log levels and different handlers, see the <a href="https://github.com/Seldaek/monolog/blob/master/doc/01-usage.md" target="_blank">Monolog GitHub page</a> and <a href="https://tools.ietf.org/html/rfc5424" target="_blank">IETF RFC 5424 </a>and <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md" target="_blank">PSR-3</a>.</p> <p>We can now view the contents of the log file to ensure functionality:<br /> <a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-01.png" target="_blank"><img style="width: 532px;height: 54px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/14/cw-screen-01.png" alt="" width="532" height="54" /></a></p> <p style="text-align: left"><strong>Syslog logging</strong></p> <p style="text-align: left">Now that we are able to write a simple log entry to a local file, our next example uses the system Syslog to log events.</p> <pre><code class="lang-php">$logger = new Logger($appName); $localFormatter = new LineFormatter(null, null, false, true); $syslogFormatter = new LineFormatter(&quot;%channel%: %level_name%: %message% %context% %extra%&quot;,null,false,true); $infoHandler = new StreamHandler(__DIR__.&quot;/&quot;.$logFile, Logger::INFO); $infoHandler-&gt;setFormatter($localFormatter); $warnHandler = new SyslogHandler($appName, $facility, Logger::WARNING); $warnHandler-&gt;setFormatter($syslogFormatter); $logger-&gt;pushHandler($warnHandler); $logger-&gt;pushHandler($infoHandler); $logger-&gt;info('Test of PHP application logging.'); $logger-&gt;warn('Test of the warning system logging.');</code></pre> <p>Here we can see that the format of the syslog messages has been changed with the value, <em>$syslogFormatter</em>. Because syslog provides a date/time with each log entry, we don’t need to include these values in our log text. The syslog facility is set to <em>local0</em> with all <em>WARNING</em> messages sent to syslog with the <em>INFO</em> level messages and <em>WARNING</em> level messages logged to our local file. You can find additional information about Syslog facilities and log levels on the <a href="https://en.wikipedia.org/wiki/Syslog" target="_blank">Syslog Wikipedia page</a>.</p> <p><a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-11.png" target="_blank"><img style="width: 754px;height: 120px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/14/cw-screen-11.png" alt="" width="754" height="120" /></a></p> <p><strong>Logging to CloudWatch Logs</strong></p> <p>Now that you’ve seen the basic use of Monolog, let’s send some logs over to CloudWatch Logs. We can use the <a href="https://github.com/maxbanton/cwh" target="_blank">Amazon Web Services CloudWatch Logs Handler for Monolog library</a> to integrate Monolog with CloudWatch Logs. In our example, an authentication application produces log information.</p> <pre><code class="lang-php">use Aws\CloudWatchLogs\CloudWatchLogsClient; use Maxbanton\Cwh\Handler\CloudWatch; use Monolog\Logger; use Monolog\Formatter\LineFormatter; use Monolog\Handler\StreamHandler; use Monolog\Handler\SyslogHandler; $logFile = &quot;testapp_local.log&quot;; $appName = &quot;TestApp01&quot;; $facility = &quot;local0&quot;; // Get instance ID: $url = &quot;http://169.254.169.254/latest/meta-data/instance-id&quot;; $instanceId = file_get_contents($url); $cwClient = new CloudWatchLogsClient($awsCredentials); // Log group name, will be created if none $cwGroupName = 'php-app-logs'; // Log stream name, will be created if none $cwStreamNameInstance = $instanceId; // Instance ID as log stream name $cwStreamNameApp = &quot;TestAuthenticationApp&quot;; // Days to keep logs, 14 by default $cwRetentionDays = 90; $cwHandlerInstanceNotice = new CloudWatch($cwClient, $cwGroupName, $cwStreamNameInstance, $cwRetentionDays, 10000, [ 'application' =&gt; 'php-testapp01' ],Logger::NOTICE); $cwHandlerInstanceError = new CloudWatch($cwClient, $cwGroupName, $cwStreamNameInstance, $cwRetentionDays, 10000, [ 'application' =&gt; 'php-testapp01' ],Logger::ERROR); $cwHandlerAppNotice = new CloudWatch($cwClient, $cwGroupName, $cwStreamNameApp, $cwRetentionDays, 10000, [ 'application' =&gt; 'php-testapp01' ],Logger::NOTICE); $logger = new Logger('PHP Logging'); $formatter = new LineFormatter(null, null, false, true); $syslogFormatter = new LineFormatter(&quot;%channel%: %level_name%: %message% %context% %extra%&quot;,null,false,true); $infoHandler = new StreamHandler(__DIR__.&quot;/&quot;.$logFile, Logger::INFO); $infoHandler-&gt;setFormatter($formatter); $warnHandler = new SyslogHandler($appName, $facility, Logger::WARNING); $warnHandler-&gt;setFormatter($syslogFormatter); $cwHandlerInstanceNotice-&gt;setFormatter($formatter); $cwHandlerInstanceError-&gt;setFormatter($formatter); $cwHandlerAppNotice-&gt;setFormatter($formatter); $logger-&gt;pushHandler($warnHandler); $logger-&gt;pushHandler($infoHandler); $logger-&gt;pushHandler($cwHandlerInstanceNotice); $logger-&gt;pushHandler($cwHandlerInstanceError); $logger-&gt;pushHandler($cwHandlerAppNotice); $logger-&gt;info('Initial test of application logging.'); $logger-&gt;warn('Test of the warning system logging.'); $logger-&gt;notice('Application Auth Event: ',[ 'function'=&gt;'login-action','result'=&gt;'login-success' ]); $logger-&gt;notice('Application Auth Event: ',[ 'function'=&gt;'login-action','result'=&gt;'login-failure' ]); $logger-&gt;error('Application ERROR: System Error');</code></pre> <p>In this example, application authentication events are passed as a PHP array and presented in CloudWatch Logs as JSON. The events with a result of <em>login-success</em> and <em>login-failure</em> are sent to both the log stream associated with the instance ID and to the log stream associated with the application name.</p> <p><a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-04.png" target="_blank"><img style="width: 640px;height: 301px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/14/cw-screen-04.png" alt="" width="640" height="301" /></a></p> <p>&nbsp;</p> <p>Using these different stream locations, we can create metrics and alarms at either a per-instance level or per-application level. Let’s assume that we want to create a metric for total number of users logged into our application over the past five minutes. Select your event group and then choose <em>Create Metric Filter</em>.</p> <p><a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-02.png" target="_blank"><img style="width: 640px;height: 106px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/14/cw-screen-02.png" alt="" width="640" height="106" /></a></p> <p>On the next page, we can create our filter and test in the same window. For the filter data, we use the JSON string from the log entry. Enter the following string to extract all the successful logins.</p> <pre>{ $.result = login-success }</pre> <p><a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/18/cw-screen-17.png" target="_blank"><img style="width: 680px;height: 538px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/18/cw-screen-17.png" alt="" width="680" height="538" /></a></p> <p>Below, we can see the filter details. I updated the Filter Name to a value that’s easy to identify. The Metric Namespace now has a value associated with the application name and the metric name reflects the number of <em>login-success</em> values.</p> <p>&nbsp;</p> <p><a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-05.png" target="_blank"><img style="width: 765px;height: 425px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/14/cw-screen-05.png" alt="" width="765" height="425" /></a></p> <p>We could now create an alarm to send a notification or perform some action (such as an Amazon EC2 scaling decision), based on this information being received via CloudWatch Logs.</p> <p><a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-07.png" target="_blank"><img style="width: 665px;height: 229px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/14/cw-screen-07.png" alt="" width="665" height="229" /></a></p> <p><a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/15/cw-screen-16.png" target="_blank"><img style="width: 600px;height: 398px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/15/cw-screen-16.png" alt="" width="600" height="398" /></a></p> <p>With these values, we would receive an alert each time there were more than 50 successful logins within a five-minute period.</p> <p><strong>Laravel logging</strong></p> <p>Monolog is used as the logging solution for a number of PHP applications and frameworks, including, the popular Laravel PHP framework. In this example, we’ll show the use of Monolog with CloudWatch Logs within Laravel. Our first step is to find out the current log settings for our Laravel application. If you open config/app.php within your application root, you see various log settings. By default, Laravel is set to log to a single log file using the baseline log level of debug.</p> <p><a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-12.png" target="_blank"><img style="width: 405px;height: 81px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/14/cw-screen-12.png" alt="" width="450" height="90" /></a></p> <p>Next, we add the AWS SDK for PHP as a service provider within Laravel using instructions and examples <a href="https://github.com/aws/aws-sdk-php-laravel" target="_blank">from here</a>.</p> <p>You also want to add the Monolog library for CloudWatch Logs to the composer.json file for inclusion in the application, as shown.<br /> <a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-13.png" target="_blank"><img style="width: 405px;height: 184px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/14/cw-screen-13.png" alt="" width="450" height="204" /></a></p> <p>You now need to extend the current Laravel Monolog configuration with your custom configuration. You can find additional information about this step on the <a href="https://laravel.com/docs/5.4/errors#custom-monolog-configuration" target="_blank">Laravel Error and Logging page</a>. The following is an example of this addition to the bootstrap/app.php file.</p> <pre><code class="lang-php">use Maxbanton\Cwh\Handler\CloudWatch; $app-&gt;configureMonologUsing( function($monolog) { $cwClient = App::make('aws')-&gt;createClient('CloudWatchLogs'); $cwGroupName = env('AWS_CWL_GROUP', 'laravel-app-logs'); $cwStreamNameApp = env('AWS_CWL_APP', 'laravel-app-name'); $cwTagName = env('AWS_CWL_TAG_NAME', 'application'); $cwTagValue = env('AWS_CWL_TAG_VALUE', 'laravel-testapp01'); $cwRetentionDays = 90; $cwHandlerApp = new CloudWatch($cwClient, $cwGroupName, $cwStreamNameApp, $cwRetentionDays, 10000, [ $cwTagName =&gt; $cwTagValue ] ); $monolog-&gt;pushHandler($cwHandlerApp); });</code></pre> <p>For testing purposes, we add a logging call to a test route in routes/web.php.</p> <pre><code class="lang-php">Route::get('/test', function () { Log::warning('Clicking on test link!!!'); return view('test'); });</code></pre> <p><a href="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/13/cw-screen-14.png" target="_blank"><img style="width: 300px;height: 79px" src="https://d2908q01vomqb2.cloudfront.net/0716d9708d321ffb6a00818614779e779925365c/2017/04/14/cw-screen-14.png" alt="" width="300" height="79" /></a></p> <p>When the test route is invoked, the logs now show in CloudWatch Logs.<br /> <a href="https://s3-us-west-2.amazonaws.com/pub-materials/SDK-Monolog/cw-screen-15.png" target="_blank"><img style="width: 523px;height: 192px" src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK-Monolog/cw-screen-15.png" width="523" height="192" /></a></p> <p><strong>Conclusion</strong></p> <p>In our examples, we’ve shown how to use PHP Monolog to log to a local file, syslog, and CloudWatch Logs. We have also demonstrated the integration of Monolog with CloudWatch Logs within a popular PHP application framework. Finally, we’ve shown how to create CloudWatch Logs metric filters and apply those to CloudWatch Alarms that make the data from the logs actionable with notifications, as well as scaling decisions. CloudWatch Logs provides a central logging capability for your PHP applications and, combined with Monolog, ensures the availability of the library for use within established projects and custom engagements.</p> Automating the Deployment of Encrypted Web Services with the AWS SDK for PHP (Part 2) https://aws.amazon.com/blogs/developer/automating-the-deployment-of-encrypted-web-services-with-the-aws-sdk-for-php-part-2/ Wed, 15 Feb 2017 21:28:17 +0000 845b9098da7f1f5d6776bc30040ebd42d3e60191 In the first post of this series, we focused on how to use Amazon Route 53 for domain registration and use Amazon Certificate Manager (ACM) to create SSL certificates. With our newly registered domain available for use, we can proceed to deploy and configure the services we need to host the www.dev-null.link website across an […] <p>In the <a href="https://aws.amazon.com/blogs/developer/automating-the-deployment-of-encrypted-web-services-with-the-aws-sdk-for-php/" target="_blank">first post of this series</a>, we focused on how to use <a href="https://aws.amazon.com/route53/" target="_blank">Amazon Route 53</a> for domain registration and use <a href="http://aws.amazon.com/acm" target="_blank">Amazon Certificate Manager (ACM)</a> to create SSL certificates. With our newly registered domain available for use, we can proceed to deploy and configure the services we need to host the <em>www.dev-null.link</em> website across an encrypted connection. Once complete, the infrastructure configuration will reflect the diagrams below.</p> <p><a href="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-P2-01.png" target="_blank"><img class="alignleft" style="width: 350px;height: 241px" src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-P2-01.png" alt="Diagram 1" width="300" height="201" /></a></p> <p><a href="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-P2-11.png" target="_blank"><img class="alignleft" style="width: 350px;height: 241px" src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-P2-11.png" alt="Diagram 2" width="300" height="201" /></a></p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>The first diagram shows the use of Route 53 to route traffic between <a href="https://aws.amazon.com/documentation/elastic-beanstalk/" target="_blank">AWS Elastic Beanstalk</a> environments across multiple regions. The second example adds <a href="https://aws.amazon.com/cloudfront/" target="_blank">Amazon CloudFront</a> support to the design.</p> <h3><span style="color: #3366ff">AWS Elastic Beanstalk</span></h3> <p>Our first step is to create the Elastic Beanstalk application, which will provide the necessary infrastructure to host our website. The following is the order of the methods used for the AWS Elastic Beanstalk deployment:</p> <ul> <li>createApplication</li> <li>createApplicationVersion</li> <li>createConfigurationTemplate</li> <li>createEnvironment</li> </ul> <p>We start by creating the Elastic Beanstalk application.</p> <pre><code class="lang-php">$ebCreateApplicationData = [ 'ApplicationName' =&gt; &quot;DevNullDemo&quot;, 'Description' =&gt; &quot;Demo application for ACM deployment&quot; ]; $ebCreateApplicationResult = $ebClient-&gt;createApplication($ebCreateApplicationData); print_r($ebCreateApplicationResult);</code></pre> <p><strong>Result</strong></p> <pre>… [Application] =&gt; Array ( [ApplicationName] =&gt; DevNullDemo [Description] =&gt; Demo application for ACM deployment … </pre> <p>Now we’ll create the initial version of the application and name it <em>DevNullDemo</em>. You can use the application archive of your&nbsp;choice, although a simple PHP demo site is available <a href="https://s3-us-west-2.amazonaws.com/pub-materials/Sample-App.zip">here</a>.</p> <pre><code class="lang-php">$ebCreateAppVersionData = [ 'ApplicationName' =&gt; &quot;DevNullDemo&quot;, 'VersionLabel' =&gt; 'v1', 'Description' =&gt; 'Initial Create', 'SourceBundle' =&gt; [ 'S3Bucket' =&gt; 'pub-materials', 'S3Key' =&gt; 'Sample-App.zip' ] ]; $ebCreateAppVersionResult = $ebClient-&gt;createApplicationVersion($ebCreateAppVersionData); print_r($ebCreateAppVersionResult);</code></pre> <p><b>Result</b></p> <pre>… [ApplicationVersion] =&gt; Array ( [ApplicationName] =&gt; DevNullDemo [Description] =&gt; Initial Create [VersionLabel] =&gt; v1 [SourceBundle] =&gt; Array ( [S3Bucket] =&gt; pub-materials [S3Key] =&gt; Sample-App.zip ) [Status] =&gt; UNPROCESSED ) … </pre> <p>Next, we need to create an Elastic Beanstalk configuration template. This template requires the selection of an <a href="http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts.platforms.html" target="_blank">Elastic Beanstalk solution stack</a> prior to calling the method, createConfigurationTemplate. The solution stack is the platform you choose to run your application within Elastic Beanstalk. You can find a list of available solution stack choices by using the <em>listAvailableSolutionStacks</em> method.</p> <pre><code class="lang-php">$ebSolutionStacks = $ebClient-&gt;listAvailableSolutionStacks(); print_r($ebSolutionStacks);</code></pre> <p><b>Result</b></p> <pre>… [SolutionStacks] =&gt; Array ( [0] =&gt; 64bit Windows Server Core 2012 R2 v1.2.0 running IIS 8.5 … [5] =&gt; 64bit Amazon Linux 2016.03 v2.1.6 running Java 7 … [9] =&gt; 64bit Amazon Linux 2014.03 v1.1.0 running Node.js [14] =&gt; 64bit Amazon Linux 2016.03 v2.1.7 running PHP 7.0 [15] =&gt; 64bit Amazon Linux 2015.09 v2.0.6 running PHP 5.6 [16] =&gt; 64bit Amazon Linux 2015.09 v2.0.4 running PHP 5.6 … [14] =&gt; Array ( [SolutionStackName] =&gt; 64bit Amazon Linux 2016.03 v2.1.7 running PHP 7.0 [PermittedFileTypes] =&gt; Array ( [0] =&gt; zip ) ) …</pre> <p>For our demonstration, we’ll use the, <strong>64bit Amazon Linux 2016.03 v2.1.7 running PHP 7.0</strong> solution stack.</p> <pre><code class="lang-php">$ebConfigTemplateData = [ 'ApplicationName' =&gt; &quot;DevNullDemo&quot;, 'TemplateName' =&gt; 'DevNullDemoTemplate', 'SolutionStackName' =&gt; '64bit Amazon Linux 2016.03 v2.1.7 running PHP 7.0', 'Description' =&gt; 'EB Environment template for blog deployment.' ]; $ebConfigTemplateCreateResult = $ebClient-&gt;createConfigurationTemplate($ebConfigTemplateData); print_r($ebConfigTemplateCreateResult);</code></pre> <p><strong>Result</strong></p> <pre>… ( [SolutionStackName] =&gt; 64bit Amazon Linux 2016.03 v2.1.7 running PHP 7.0 [ApplicationName] =&gt; DevNullDemo [TemplateName] =&gt; DevNullDemoTemplate [Description] =&gt; EB Environment template for blog deployment. …</pre> <p>Now we can create and start the infrastructure by using the <em>createEnvironment</em> method. The following example sets additional options such as instance type and ACM SSL certificate. You need to replace the <strong>[CERTIFICATEARN]</strong>&nbsp;value with the AWS ACM certificate ARN created in <a href="https://aws.amazon.com/blogs/developer/automating-the-deployment-of-encrypted-web-services-with-the-aws-sdk-for-php/" target="_blank">part 1 of this series</a>. You can also find this value by using the AWS ACM <em>listCertificates</em> method. For these examples, we’ve created a certificate across multiple regions for the host name <em>eb.dev-null.link</em>, in addition to the previously created <em>www.dev-null.link</em> certificate.</p> <pre><code class="lang-php">$ebCreateEnvData = [ 'ApplicationName' =&gt; &quot;DevNullDemo&quot;, 'EnvironmentName' =&gt; &quot;DevNullEnv&quot;, 'Description' =&gt; &quot;Demo environment for ACM EB deployment.&quot;, 'TemplateName' =&gt; &quot;DevNullDemoTemplate&quot;, 'VersionLabel' =&gt; 'v1', 'OptionSettings' =&gt; [ [ 'Namespace' =&gt; 'aws:elb:listener:443', 'OptionName' =&gt; 'ListenerProtocol', 'Value' =&gt; 'HTTPS' ], [ 'Namespace' =&gt; 'aws:elb:listener:443', 'OptionName' =&gt; 'SSLCertificateId', 'Value' =&gt; '[CERTIFICATEARN]' ], [ 'Namespace' =&gt; 'aws:elb:listener:443', 'OptionName' =&gt; 'InstancePort', 'Value' =&gt; '80' ], [ 'Namespace' =&gt; 'aws:elb:listener:443', 'OptionName' =&gt; 'InstanceProtocol', 'Value' =&gt; 'HTTP' ], [ 'Namespace' =&gt; 'aws:autoscaling:launchconfiguration', 'OptionName' =&gt; 'InstanceType', 'Value' =&gt; 't2.nano' ], ], 'Tier' =&gt; [ 'Name' =&gt; 'WebServer', 'Type' =&gt; 'Standard', 'Version' =&gt; ' ' ], ]; $ebCreateEnvData = $ebClient-&gt;createEnvironment($ebCreateEnvData); print_r($ebCreateEnvData); </code></pre> <p><strong>Result</strong></p> <pre>… [EnvironmentName] =&gt; DevNullEnv [EnvironmentId] =&gt; e-fnvhjptdjd [ApplicationName] =&gt; DevNullDemo [VersionLabel] =&gt; v1 [SolutionStackName] =&gt; 64bit Amazon Linux 2016.03 v2.1.7 running PHP 7.0 [Description] =&gt; Demo environment for ACM EB deployment. [Status] =&gt; Launching [Health] =&gt; Grey [Tier] =&gt; Array ( [Name] =&gt; WebServer [Type] =&gt; Standard [Version] =&gt; ) …</pre> <p>As the results show, the current status of our environment is <em>Launching</em>. We can periodically check the status with the <em>describeEnvironments</em> method.</p> <pre><code class="lang-php">$ebDescEnvResult = $ebClient-&gt;describeEnvironments(); foreach($ebDescEnvResult['Environments'] as $ebEnvList) { print &quot;Name:\t&quot;.$ebEnvList['EnvironmentName'].&quot;\n&quot;; print &quot;ID:\t&quot;.$ebEnvList['EnvironmentId'].&quot;\n&quot;; print &quot;CNAME:\t&quot;.$ebEnvList['CNAME'].&quot;\n&quot;; print &quot;Status:\t&quot;.$ebEnvList['Status'].&quot;\n\n&quot;; } </code></pre> <p><strong>Result</strong></p> <pre>Name: DevNullEnv ID: [ID] CNAME: DevNullEnv.[ID].[Region].elasticbeanstalk.com Status: Ready </pre> <p>When the environment has a status of <em>Ready</em>, we can proceed to create the necessary DNS records. You can also check that the site is functional by pasting the CNAME value into a web browser. Be sure to record this CNAME value so you can use it later.</p> <p><a href="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-P2-05.png" target="_blank"><img style="width: 600px" src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-P2-05.png" alt="Demo App" /></a></p> <p>You will want to repeat this process across additional AWS Regions to demonstrate latency-based DNS resolution.</p> <h3><span style="color: #3366ff">Amazon Route 53</span></h3> <p>Our next step is to create a Route 53 hosted zone. This hosted zone will define a domain name (or subdomain) for which we are authoritative and, thus, allowed to create DNS records. We’ll start with the <em>createHostedZone</em> method.</p> <pre><code class="lang-php">$route53Client = $sdk-&gt;createRoute53(); $route53Data = [ 'Name' =&gt; &quot;dev-null.link&quot;, 'CallerReference' =&gt; &quot;BLOGPOSTREF001&quot;, 'HostedZoneConfig' =&gt; [ 'Comment' =&gt; &quot;AWS SDK sample dev-null.link&quot; ] ]; $route53Result = $route53Client-&gt;createHostedZone($route53Data); </code></pre> <p><strong>Result</strong></p> <pre> [HostedZone] =&gt; Array ( [Id] =&gt; /hostedzone/[Amazon Route 53 Zone ID] [Name] =&gt; dev-null.link. [CallerReference] =&gt; BLOGPOSTREF001 [Config] =&gt; Array ( [Comment] =&gt; AWS SDK sample dev-null.link [PrivateZone] =&gt; ) [ResourceRecordSetCount] =&gt; 2 ) … [DelegationSet] =&gt; Array ( [NameServers] =&gt; Array ( [0] =&gt; ns-999.awsdns-60.net … ) ) </pre> <p>You should copy the ID of the hosted zone from this result. You can also find a list of all hosted zone ID values by using the <em>listHostedZones</em> method.</p> <pre><code class="lang-php">$route53ListResult = $route53Client-&gt;listHostedZones(); foreach($route53ListResult['HostedZones'] as $zoneItem) { print &quot;Name:\t&quot;.substr($zoneItem['Name'],0,-1).&quot;\n&quot;; print &quot;ID:\t&quot;.$zoneItem['Id'].&quot;\n\n&quot;; } </code></pre> <p><strong>Result</strong></p> <pre>Name: dev-null.link ID: /hostedzone/[Amazon Route 53 Zone ID] </pre> <p>We’ll now create a new DNS entry so that our website is visible via web browser with the <em>eb.dev-null.link</em> host name. For this, we need to use the CNAME value from our Elastic Beanstalk application.</p> <pre><code class="lang-php">$currentDate = date(&quot;r&quot;); $hostedZoneId = &quot;/hostedzone/[Amazon Route 53 Zone ID]&quot;; $subDomain = &quot;eb.dev-null.link&quot;; $ebCname = &quot;DevNullEnv.[EB ID].[Region].elasticbeanstalk.com&quot;; $recordComment = &quot;Created $subDomain record on $currentDate&quot;; $route53RecordData = [ 'HostedZoneId' =&gt; $hostedZoneId, 'ChangeBatch' =&gt; [ 'Comment' =&gt; $recordComment, 'Changes' =&gt; [ [ 'Action' =&gt; 'CREATE', 'ResourceRecordSet' =&gt; [ 'Name' =&gt; $subDomain, 'Type' =&gt; 'CNAME', 'TTL' =&gt; 60, 'ResourceRecords' =&gt; [ [ 'Value' =&gt; $ebCname ] ] ] ] ] ] ]; $route53ChangeResult = $route53Client-&gt;changeResourceRecordSets($route53RecordData); print_r($route53ChangeResult); </code></pre> <p><strong>Result</strong></p> <pre>… [ChangeInfo] =&gt; Array ( [Id] =&gt; /change/[ChangeInfo ID] [Status] =&gt; PENDING … [Comment] =&gt; Created test.jf.unicorn.rentals record on Thu, 15 Sep 2016 12:25:07 -0700 ) … </pre> <p>As we can see from the result, the status of the change is <strong>PENDING</strong>. We can check the status with the <em>getChange</em> method using the value of the <em>ChangeInfo ID</em>.</p> <pre><code class="lang-php">$route53ChangeData = [ 'Id' =&gt; &quot;/change/[ChangeInfo ID]&quot; ]; $route53ChangeResult = $route53Client-&gt;getChange($route53ChangeData); print_r($route53ChangeResult); </code></pre> <p><strong>Result</strong></p> <pre>… [ChangeInfo] =&gt; Array ( [Id] =&gt; /change/&lt;ChangeInfo ID&gt; [Status] =&gt; INSYNC … [Comment] =&gt; Created test.jf.unicorn.rentals record on Thu, 15 Sep 2016 12:25:07 -0700 ) … </pre> <p>Now that our change has the status of <strong>INSYNC</strong>, we can view the secure URL in our browser window with the URL <em>https://eb.dev-null.link/</em>.<br /> <a href="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-P2-09.png" target="_blank"><img style="width: 500px" src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-P2-09.png" alt="Demo App" /></a></p> <h3><span style="color: #3366ff">Deploying Across Multiple Regions</span></h3> <p>This deployment is now serving our website across an encrypted connection in a single AWS Region. For those who would like to use multiple regions, we can expand our current configuration. An AWS ACM certificate is needed in each AWS Region used for the deployment. Because we’ll be using CloudFront, we have to ensure that a certificate is created in the <strong>us-east-1</strong> region because CloudFront will source the available AWS ACM certificates from there. You can reference <a href="https://aws.amazon.com/blogs/developer/automating-the-deployment-of-encrypted-web-services-with-the-aws-sdk-for-php/" target="_blank">the previous blog post</a> for instructions on creating an AWS ACM certificate in additional regions. Next, run the Elastic Beanstalk creation methods shown earlier in each additional region where you want to deploy the application. Be sure to record the CNAME value for each environment.</p> <p>After we have all of the necessary Elastic Beanstalk environments running, we need to delete the Route 53 resource record for <em>eb.dev-null.link</em> so that we can replace it with a latency-based record set.</p> <pre><code class="lang-php">$recordComment = &quot;Deleted $subDomain record on $currentDate&quot;; $route53RecordData = [ 'HostedZoneId' =&gt; $hostedZoneId, 'ChangeBatch' =&gt; [ 'Comment' =&gt; $recordComment, 'Changes' =&gt; [ [ 'Action' =&gt; 'DELETE', 'ResourceRecordSet' =&gt; [ 'Name' =&gt; $subDomain, 'Type' =&gt; 'CNAME', 'TTL' =&gt; 60, 'ResourceRecords' =&gt; [ [ 'Value' =&gt; $ebCname ] ] ] ] ] ] ]; $route53ChangeResult = $route53Client-&gt;changeResourceRecordSets($route53RecordData); </code></pre> <p>You might notice that the method and instructions to delete the record are almost identical to the instructions used to create the record. They even use the same method, <em>changeResourceRecordSets</em>.</p> <p><strong>Result</strong></p> <pre>… [ChangeInfo] =&gt; Array ( [Id] =&gt; /change/[ChangeInfo ID] [Status] =&gt; PENDING [Comment] =&gt; Deleted www.dev-null.link record on Thu, 15 Sep 2016 14:58:51 -0700 ) … </pre> <p>Our next step is to add the latency-based routing rules. This example provides the CNAME of the Elastic Beanstalk environment via the <em>describeEnvironments</em> method.</p> <pre><code class="lang-php">$currentDate = date(&quot;r&quot;); $hostedZoneId = &quot;HOSTED ZONE ID&quot;; $ebDescEnvData = [ 'EnvironmentNames' =&gt; [ 'DevNullEnvProd' ] ]; $ebDescEnvResult = $ebClient-&gt;describeEnvironments($ebDescEnvData); $ebCname = $ebDescEnvResult['Environments'][0]['CNAME']; $recordComment = &quot;Created www record on $currentDate&quot;; $route53RecordData = [ 'HostedZoneId' =&gt; $hostedZoneId, 'ChangeBatch' =&gt; [ 'Comment' =&gt; $recordComment, 'Changes' =&gt; [ [ 'Action' =&gt; 'CREATE', 'ResourceRecordSet' =&gt; [ 'Name' =&gt; &quot;eb.dev-null.link&quot;, 'Type' =&gt; 'CNAME', 'TTL' =&gt; 60, 'Region' =&gt; $region, 'SetIdentifier' =&gt; str_replace(&quot;-&quot;,&quot;&quot;,$region), 'ResourceRecords' =&gt; [ [ 'Value' =&gt; $ebCname ], ], ], ], ], ], ]; $route53ChangeResult = $route53Client-&gt;changeResourceRecordSets($route53RecordData); </code></pre> <p><strong>Result</strong></p> <pre>… [ChangeInfo] =&gt; Array ( [Id] =&gt; /change/[ChangeInfo ID] [Status] =&gt; PENDING … </pre> <p><a href="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-P2-010.png" target="_blank"><img src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-P2-010.png" alt="Demo App" /></a></p> <p>In the Route 53 console, we can see there are two CNAMEs that now resolve the host name, <em>eb.dev-null.link</em>. When a user visits the website, the URL returned will correspond to the lower of the record latencies.</p> <h3><span style="color: #3366ff">Amazon CloudFront</span></h3> <p>To enhance the user experience, we’ll now configure and deploy a content delivery network solution named <a href="https://aws.amazon.com/cloudfront/" target="_blank">Amazon CloudFront</a>. This AWS service provides content delivery acceleration for the media provided with our web application. Each CloudFront deployment is composed of a CloudFront distribution with each distribution having one or more origins. An origin defines the mapping of a URL to a particular destination. The host name, <em>www.dev-null.link</em>, will resolve to our CloudFront distribution, which will then serve pages from the backend <em>eb.dev-null.link</em> load-balanced site. We first create our distribution with the <em>createDistribution</em> method. The value of <strong>$cfCreateDistData</strong> can be found in <a href="https://gist.github.com/aws-joe/416a1189eb67359b0627b4a9aa95a9d6" target="_blank">this Github Gist</a>.</p> <pre><code class="lang-php">$cfCreateDistResult = $cfClient-&gt;createDistribution($cfCreateDistData); print_r($cfCreateDistResult); </code></pre> <p><strong>Result</strong></p> <pre>Aws\Result Object ( [data:Aws\Result:private] =&gt; Array ( [Distribution] =&gt; Array ( [Id] =&gt; [CF ID Value] [DomainName] =&gt; [CloudFront ID].cloudfront.net … </pre> <p>Once complete, we need to save the value of <em>DomainName</em> from the result returned. Next, we’ll create a new Route 53 CNAME record that points <em>www.dev-null.link</em> to our CloudFront distribution.</p> <pre><code class="lang-php">$subDomain = &quot;www.dev-null.link&quot;; $cfCname = &quot;[CloudFront ID].cloudfront.net&quot;; $recordComment = &quot;Created $subDomain record on $currentDate&quot;; $route53RecordData = [ 'HostedZoneId' =&gt; $hostedZoneId, 'ChangeBatch' =&gt; [ 'Comment' =&gt; $recordComment, 'Changes' =&gt; [ [ 'Action' =&gt; 'CREATE', 'ResourceRecordSet' =&gt; [ 'Name' =&gt; $subDomain, 'Type' =&gt; 'CNAME', 'TTL' =&gt; 60, 'ResourceRecords' =&gt; [ [ 'Value' =&gt; $cfCname ] ] ] ] ] ] ]; $route53ChangeResult = $route53Client-&gt;changeResourceRecordSets($route53RecordData); </code></pre> <p><strong>Result</strong></p> <pre>Aws\Result Object ( [data:Aws\Result:private] =&gt; Array ( [ChangeInfo] =&gt; Array ( [Status] =&gt; PENDING … </pre> <p>Once complete, we can test the new deployment by navigating to the URL (<em>https://www.dev-null.link/</em>) in a web browser.</p> <h3><span style="color: #3366ff">Conclusion</span></h3> <p>With our infrastructure configuration completed, we now have a globally load balanced web application that’s accessible via encrypted communications. We’ve shown we can use the AWS SDK for PHP to automate these deployments, which provides the agility to reproduce these environments for customers on demand. Next, we’ll continue this series by reviewing deployments that use <a href="http://aws.amazon.com/s3" target="_blank">Amazon S3</a> for static content hosting, and the <a href="https://aws.amazon.com/elasticloadbalancing/applicationloadbalancer/" target="_blank">AWS Application Load Balancer</a> and <a href="http://aws.amazon.com/elasticloadbalancing" target="_blank">Elastic Load Balancing</a> with <a href="http://aws.amazon.com/ec2" target="_blank">Amazon EC2</a> instance deployments.</p> Automating the Deployment of Encrypted Web Services with the AWS SDK for PHP https://aws.amazon.com/blogs/developer/automating-the-deployment-of-encrypted-web-services-with-the-aws-sdk-for-php/ Tue, 06 Dec 2016 22:40:07 +0000 2d6a114c8015b71893396394d2ceaedf120833c0 Having worked in the web hosting space, one of the areas I find so fun about AWS is the ease of automating tasks that have historically been quite disjointed. &nbsp;The process of supporting a customer request to register a domain, create or update DNS entries, configure the load balancer, deploy servers, etc., had me working […] <p>Having worked in the web hosting space, one of the areas I find so fun about AWS is the ease of automating tasks that have historically been quite disjointed. &nbsp;The process of supporting a customer request to register a domain, create or update DNS entries, configure the load balancer, deploy servers, etc., had me working across a multitude of systems, interfaces, and APIs. &nbsp;Now, with the release of AWS Certificate Manager (ACM) in addition to existing AWS services, AWS provides all the tools and capabilities needed to support the provisioning of these services within customer accounts.</p> <p>In this three-part series of posts, we’ll review how to use the <a href="https://aws.amazon.com/sdk-for-php/" target="_blank">AWS SDK for PHP </a>to automate web service deployment, domain registration, DNS administration, and SSL certificate generation and assignment. &nbsp;Using the examples outlined in these posts, as well as other features and functions of the AWS SDK for PHP, you’ll learn how to programmatically create a process for automatically purchasing a domain and then deploying an HTTPS (SSL-secured) web service on AWS by using either <a href="https://aws.amazon.com/ec2/" target="_blank">Amazon EC2 </a>or <a href="https://aws.amazon.com/elasticbeanstalk/" target="_blank">AWS Elastic Beanstalk</a>.</p> <p>The examples in this post focus on using <a href="https://aws.amazon.com/route53/" target="_blank">Amazon Route 53 </a>to automate the registration of domain names and DNS administration. &nbsp;Next, we’ll showcase how to use ACM to create and manage SSL certificates. &nbsp;In subsequent posts, we will show how to automate the setup of encrypted HTTPS web services with the new domain and newly created certificates on Elastic Beanstalk. &nbsp;Then, we’ll show how to automate deployments to EC2 and <a href="https://aws.amazon.com/elasticloadbalancing/" target="_blank">Elastic Load Balancing</a>. &nbsp;Once complete, we’ll have two web application stacks. &nbsp;We’ll run the www.dev-null.link site from Elastic Beanstalk, and use EC2 and Elastic Load Balancing to run the second web application stack. &nbsp;The following diagrams illustrate the final designs.</p> <p><a href="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-18.png" target="_blank"><img style="width: 200px; height: 132px;" src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-18.png" alt="" /></a>&nbsp;&nbsp;<a href="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-23.png" target="_blank"><img style="width: 200px; height: 132px;" src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-23.png" alt="" /></a>&nbsp;<a href="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-25.png" target="_blank"><img style="width: 199px; height: 133px;" src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-25.png" alt="" /></a></p> <h2><span style="font-size: 16px;"><span style="color: #3399ff;">Amazon Route53 Domain Registration</span></span></h2> <p>The first task in building the web infrastructure is to identify and register an available domain name. &nbsp;We can use the AWS SDK for PHP to check domain name availability. &nbsp;We will use a method called checkDomainAvailability, which is part of the Route 53 Domains client. &nbsp;We can automate the process of testing domains until we have a name that meets our application’s needs and is also available for registration. &nbsp;The example below loops through an array of domain names, listing their current status for registration.</p> <pre><code class="lang-php">$route53Client = $sdk-&gt;createRoute53Domains(); $domainNames = [ &quot;test.com&quot;, &quot;dev.com&quot;, &quot;dev-null.link&quot;, &quot;null38.link&quot; ]; foreach($domainNames as $domainNameElement) { $route53CheckDomainAvailData = [ 'DomainName' =&gt; $domainNameElement ]; $route53CheckDomainResults = $route53Client-&gt;checkDomainAvailability($route53CheckDomainAvailData); print &quot;Domain $domainNameElement is &quot;.$route53CheckDomainResults['Availability'].&quot;n&quot;; }</code></pre> <div> <p>You can view the results of the check below.</p> </div> <div> <p><img style="width: 249px; height: 67px;" src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-11.png" alt="" /></p> </div> <div> There are two domain names available for registration. &nbsp;In this example, we’ll register the domain <strong>dev-null.link</strong>. &nbsp;This name contains the “.link” top-level domain (TLD), and the “dev-null” second-level domain. Now, register the domain by using the registerDomain method. &nbsp;The registration has several required fields that we need to complete. These requirements are specific to each top level domain. For this example, we can use the following data ( <a href="https://gist.github.com/aws-joe/806fce8e111201c13e7098e964bab248">provided in this Github Gist</a>): </div> <pre><code class="lang-php">$route53DomainRegData = [ 'AdminContact' =&gt; [ 'AddressLine1' =&gt; $address1, 'AddressLine2' =&gt; $address2, 'City' =&gt; $city, 'ContactType' =&gt; 'PERSON', 'CountryCode' =&gt; 'US', ..... $route53Client = $sdk-&gt;createRoute53Domains(); $route53CreateDomRes = $r53Client-&gt;registerDomain($route53DomainRegData); print_r($route53DomainRegData);</code></pre> <p>Notice that the PhoneNumber data element must be in the format of &nbsp;“+1.1231231212” to be valid.</p> <div> <div> <div> We can now register the domain as follows. </div> <pre class="brush: bash">[user@dev1 scripts]# php aws-route53-register-domain.php ... [statusCode] =&gt; 200 [effectiveUri] =&gt; https://route53domains.us-east-1.amazonaws.com ... </pre> </div> <div> <p>While we wait for the registration process to finish, we can check on the status of the domain. &nbsp;First, use the listOperations method to print the list of current operations, and then enter the operation number into the getOperationDetail method. &nbsp;Let’s look at all of the pending operations with the code.</p> <div> <pre><code class="lang-php">$route53ListOperationsResults = $route53Client-&gt;listOperations(); print_r($route53ListOperationsResults); $route53OperDetails = [ 'OperationId' =&gt; $operationId ]; $route53OperResults = $route53Client-&gt;getOperationDetail($route53OperDetails); print_r($route53OperResults); </code></pre> </div> <p><b>Result</b></p> <pre class="brush: bash">[user@dev1 scripts]# [user@dev1 scripts]# php aws-route53-list-operations.php … [Status] =&gt; IN_PROGRESS [Type] =&gt; REGISTER_DOMAIN … </pre> <p>AWS Certificate Manager</p> <p>With ACM, we&nbsp;no longer have to worry about certificate expirations, securing the certificate private keys, copying self-signed CA certificates to clients, making sure servers all have the right certificate, or even the cost of a managed SSL certificate. &nbsp;AWS provides managed SSL certificates at no cost. &nbsp;Also, AWS handles the responsibility of renewing the certificate and placing it on the devices used to terminate SSL connections. &nbsp;ACM can be used across managed AWS services such as ELB, <a href="https://aws.amazon.com/cloudfront/" target="_blank">Amazon CloudFront</a>, and Elastic Beanstalk.</p> <h2><span style="font-size: 16px;"><span style="color: #3399ff;">ACM in Action</span></span></h2> <p>Let’s go through how to create multiple certificates to secure connections to different websites.&nbsp; We must first request a new certificate with the corresponding public and private keys.&nbsp; The requestCertificate method automates this process.</p> <p>The following example shows how to generate the certificate for our first domain.</p> </div> </div> <div> <pre><code class="lang-php">$acmClient = $sdk-&gt;createAcm(); $acmRequestCertData = [ 'DomainName' =&gt; &quot;www.dev-null.link&quot;, 'DomainValidationOptions' =&gt; [ [ 'DomainName' =&gt; &quot;www.dev-null.link&quot;, 'ValidationDomain' =&gt; &quot;dev-null.link&quot;, ], ], 'IdempotencyToken' =&gt; 'TOKENSTRINGDEVNULL01', 'SubjectAlternativeNames' =&gt; ['dev-null.link', 'images.dev-null.link'], ]; $acmRequestCertResults = $acmClient-&gt;requestCertificate($acmRequestCertData); print_r($acmRequestCertResults);</code></pre> <div> <p><b>Result</b></p> <div> <pre class="brush: bash">[user@dev1 scripts]# php aws-acm-requestCertificate.php ... [CertificateArn] =&gt; arn:aws:acm:us-east-1:ACCOUNTID:certificate/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX [@metadata] =&gt; Array ( [statusCode] =&gt; 200 ... &nbsp; </pre> <div> <p>SubjectAlternativeNames identifies other DNS entries that the certificate should cover.&nbsp; In this example, they are all subdomains of dev-null.link but can also include other domain names that could be used synonymously with our requested domain.&nbsp; You can repeat this call for any additional certificates you need.&nbsp; Be sure to update the value of IdempotencyToken for each certificate request created.&nbsp; You should save the value of CertificateArn because you’ll need to use it later.</p> </div> <div> We want to secure the primary hostname <strong>www.dev-null.link</strong>. &nbsp;ACM requires validation for the domain from an email address that is tied to the registration information. &nbsp;Domain validation requests are sent to multiple locations. &nbsp;These validation emails are sent to domain email addresses in the following order: admin@dev-null.link, administrator@dev-null.link, hostmaster@dev-null.link, postmaster@dev-null.link, and webmaster@dev-null.link. &nbsp;In addition, a validation request is also sent to the email contacts for the Administrative, Technical, and Domain Registrant. &nbsp;The following figure shows a copy of the received email. </div> </div> <div></div> <div> <a href="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-20.png" target="_blank"><img style="width: 250px; height: 251px;" src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-20.png" alt="" /></a> </div> <div></div> <div> <p>When you click the link in the email, you’re taken to the page shown below.</p> <p><a href="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-21.png" target="_blank"><img style="width: 251px; height: 123px;" src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-21.png" alt="" /></a></p> <p>Next, click&nbsp;<strong>I Approve</strong>.&nbsp; A confirmation page appears that you can save for your records.</p> <p><a href="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-22.png" target="_blank"><img style="width: 249px; height: 83px;" src="https://s3-us-west-2.amazonaws.com/pub-materials/SDK/ACM-22.png" alt="" /></a></p> </div> </div> <div> <p>Let’s now use the listCertificates and describeCertificate methods to show all of the certificates we’ve generated.</p> <pre><code class="lang-php">$acmListCertResults = $acmClient-&gt;listCertificates(); print_r($acmListCertResults);</code></pre> <p><b>Result</b></p> <pre class="brush: bash">[user@dev1 scripts]# php aws-acm-list.php ... [CertificateSummaryList] =&gt; Array ... [CertificateArn] =&gt; arn:aws:acm:us-east-1:ACCOUNTID:certificate/CERTIFICATE-ID [DomainName] =&gt; www.dev-null.link ... [CertificateArn] =&gt; arn:aws:acm:us-east-1:ACCOUNTID:certificate/CERTIFICATE-ID [DomainName] =&gt; api.dev-null.link ... &nbsp; <span style="font-family: Arial, Verdana, sans-serif;">You can view details about the certificates by calling the describeCertificates method with the CertificateARN received from the previous listCertificates call.</span></pre> </div> <pre><code class="lang-php">$certificateArn = $acmListCertResults['CertificateSummaryList'][0]['CertificateArn']; $acmDescribeCertData = [ 'CertificateArn' =&gt; $certificateArn ]; $acmDescribeCertResults = $acmClient-&gt;describeCertificate($acmDescribeCertData); print_r($acmDescribeCertResults);</code></pre> <div> <p>You can view the full <a href="http://gist.github.com/aws-joe/a8304b8f8a4647c0ba8f5c5538b1f62f" target="_blank">output here </a>with abbreviated output shown below.</p> <pre class="brush: bash">[Certificate] =&gt; ... Array ( [CertificateArn] =&gt; CERTIFICATE-ARN [DomainName] =&gt; www.dev-null.link [SubjectAlternativeNames] =&gt; Array ( [0] =&gt; www.dev-null.link [1] =&gt; dev-null.link [2] =&gt; images.dev-null.link ) ...</pre> <div> <p>Finally, view the full certificate with the certificate chain.</p> <pre><code class="lang-php">$acmGetCertificateData = [ 'CertificateArn' =&gt; $certificateArn ]; $acmGetCertificateResults = $acmClient-&gt;getCertificate($acmGetCertificateData); print_r($acmGetCertificateResults);</code></pre> <div> <div> <b>Result</b> </div> <pre class="brush: bash">[Certificate] =&gt; -----BEGIN CERTIFICATE----- … -----END CERTIFICATE----- [CertificateChain] =&gt; -----BEGIN CERTIFICATE----- … -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- … -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- … -----END CERTIFICATE----- [@metadata] =&gt; Array ( [statusCode] =&gt; 200 … </pre> <div> <div> This code will return the public certificate and the chain of trust leading to the public CA that is signing the certificate allowing web browsers to trust the website being visited. </div> <div></div> <div> To get more information about the certificate and the request process, we can use the describeCertificate method. &nbsp;This method takes the certificateArn value as input and produces information about the referenced certificate. &nbsp;This information includes the list of email addresses that received validation emails, the encryption algorithm used, the certificate creation and expiration dates, and the full list of host names covered by the certificate. &nbsp;Looking forward, we can delete certificates and resend the validation email with the available ACM methods. </div> <div></div> <div> Now that we’ve covered the setup, configuration, and deployment of ACM and DNS, we now have a registered domain available for use. &nbsp;In the next post, we’ll review how to use the domain, dev-null.link, for our website. &nbsp;We’ll deploy an HTTPS website that is secured with SSL/TLS by using the AWS SDK with ELB, Amazon EC2, and Elastic Beanstalk. &nbsp;We’ll also cover creating and deleting Amazon Route 53 resource records, and how to assign our ACM certificate to newly created load balancers. </div> </div> </div> </div> </div> <p>&nbsp;</p> </div> <p>&nbsp;</p> Concurrency in Version 3 of the AWS SDK for PHP https://aws.amazon.com/blogs/developer/concurrency-in-version-3-of-the-aws-sdk-for-php/ Tue, 07 Jun 2016 23:38:37 +0000 02418dbf665bd6f4536e7177154225c72882de28 From executing API commands in the background to grouping commands and waiters into concurrent pools, version 3 of the AWS SDK for PHP lets you write asynchronous code that blocks only when you need it to. In this blog post, I’ll show you how to take advantage of some of the SDK’s concurrency abstractions, including […] <p> From executing API commands in the background to grouping commands and waiters into concurrent pools, version 3 of the AWS SDK for PHP lets you write asynchronous code that blocks only when you need it to. In this blog post, I’ll show you how to take advantage of some of the SDK’s concurrency abstractions, including promises, command pools, and waiters.</p> <h2> Promises</h2> <p> The AWS SDK for PHP makes extensive use of promises internally, relying on the <a href="https://github.com/guzzle/promises">Guzzle Promises library</a>. Each operation defined on an API supported by the SDK has an asynchronous counterpart that can be invoked by tacking <code>Async</code> to the name of the operation. An asynchronous operation will immediately return a promise that will be fulfilled with the result of the operation or rejected with an error:</p> <pre class="brush: php"> $s3Client = new AwsS3S3Client([ ‘region’ =&gt; ‘us-west-2’, ‘version’ =&gt; ‘2006-03-01’, ]); // This call will block until a response is obtained $buckets = $s3Client-&gt;listBuckets(); // This call will not block $promise = $s3Client-&gt;listBucketsAsync(); // You can provide callbacks to invoke when the request finishes $promise-&gt;then( function (AwsResultInterface $buckets) { echo ‘My buckets are: ‘ . implode(‘, ‘, $buckets-&gt;search(‘Buckets[].Name’)); }, function ($reason) { echo &quot;The promise was rejected with {$reason}&quot;; } ); </pre> <p> The Guzzle promises returned by asynchronous operations have a <code>wait</code> method that you can call if you need to block until an operation is completed. In fact, synchronous operations like <code>$s3Client-&gt;listBuckets()</code> are calling asynchronous operations under the hood and then waiting on the result.</p> <p> Where promises really shine, though, is in groupings. Let’s say you need to upload ten files to an Amazon S3 bucket. Rather than simply loop over the files and upload them one by one, you can create ten promises and then wait for those ten requests to be complete:</p> <pre class="brush: php"> $filesToUpload = [ ‘/path/to/file/1.ext’, ‘/path/to/file/2.ext’, … ‘/path/to/file/10.ext’, ]; $promises = []; foreach ($filesToUpload as $path) { $promises []= $s3Client-&gt;putObjectAsync([ ‘Bucket’ =&gt; $bucketName, ‘Key’ =&gt; basename($path), ‘SourceFile’ =&gt; $path, ]); } // Construct a promise that will be fulfilled when all // of its constituent promises are fulfilled $allPromise = GuzzleHttpPromiseall($promises); $allPromise-&gt;wait(); </pre> <p> Rather than taking ten times as long as uploading a single file, the asynchronous code above will perform the uploads concurrently. For more information about promises, see the&nbsp;<a href="http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/promises.html">AWS SDK for PHP User Guide</a>.</p> <h2> Waiters</h2> <p> Some AWS operations are naturally asynchronous (for example, those in which a successful response means that a process has been started, but is not necessarily complete). Provisioning Amazon EC2 instances or S3 buckets are gppd examples. If you were starting a project that required three S3 buckets and an Amazon ElastiCache cluster, you might start out by provisioning those resources programmatically:</p> <pre class="brush: php"> $sdk = new AwsSdk([‘region’ =&gt; ‘us-west-2’, ‘version’ =&gt; ‘latest’]); $elasticacheClient = $sdk-&gt;get(‘elasticache’); $s3Client = $sdk-&gt;get(‘s3’); $promises = []; for ($i = 0; $i &lt; 3; $i++) { $promises []= $s3Client-&gt;createBucket([ ‘Bucket’ =&gt; “my-bucket-$i”, ]); } $cacheClusterId = uniqid(‘cache’); $promises []= $elasticacheClient-&gt;createCacheCluster([ ‘CacheClusterId’ =&gt; $cacheClusterId, ]); $metaPromise = GuzzleHttpPromiseall($promises); $metaPromise-&gt;wait(); </pre> <p> Waiting on the <code>$metaPromise</code> will block only until all of the requests sent by the <code>createBucket</code> and <code>createCacheCluster</code> operations have been completed.You would need to use a <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/waiters.html">waiter</a>&nbsp;to block until those resources are available. For example, you can wait on a single bucket with an <code>S3Client</code>’s <code>waitUntil</code> method:</p> <div> $s3Client-&gt;waitUntil(‘BucketExists’, [‘Bucket’ =&gt; $bucketName]); <br /> <span style="font-family: Arial, Verdana, sans-serif">Like operations, waiters can also return promises, allowing you to compose meta-waiters from individual waiters:</span> </div> <pre class="brush: php"> $waiterPromises = []; for ($i = 0; $i &lt; 3; $i++) { // Create a waiter $waiter = $s3Client-&gt;getWaiter(‘BucketExists’, [ ‘Bucket’ =&gt; “my-bucket-$i”, ]); // Initiate the waiter and retrieve a promise. $waiterPromises []= $waiter-&gt;promise(); } $waiterPromises []= $elasticacheClient -&gt;getWaiter(‘CacheClusterAvailable’, [ ‘CacheClusterId’ =&gt; $cacheClusterId, ]) -&gt;promise(); // Composer a higher-level promise from the individual waiter promises $metaWaiterPromise = GuzzleHttpPromiseall($waiterPromises); // Block until all waiters have completed $metaWaiterPromise-&gt;wait(); </pre> <h2> Command Pools</h2> <p> The SDK also allows you to use&nbsp;<a href="http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/commands.html#commandpool">command pools</a>&nbsp;to fine-tune the way in which a series of operations are performed concurrentl. Command pools are created with a client object and an iterable list of commands, which can be created by calling <code>getCommand</code> with an operation name on any SDK client:</p> <pre class="brush: php"> // Create an S3Client $s3Client = new AwsS3S3Client([ ‘region’ =&gt; ‘us-west-2’, ‘version’ =&gt; ‘latest’, ]); // Create a list of commands $commands = [ $s3Client-&gt;getCommand(‘ListObjects’, [‘Bucket’ =&gt; ‘bucket1’]), $s3Client-&gt;getCommand(‘ListObjects’, [‘Bucket’ =&gt; ‘bucket2’]), $s3Client-&gt;getCommand(‘ListObjects’, [‘Bucket’ =&gt; ‘bucket3’]), ]; // Create a command pool $pool = new AwsCommandPool($s3Client, $commands); // Begin asynchronous execution of the commands $promise = $pool-&gt;promise(); // Force the pool to complete synchronously $promise-&gt;wait(); </pre> <p> How is this different from gathering promises from individual operations, such as by calling <code>$s3Client-&gt;listObjectsAsync(…)</code>? One key difference is that no action is taken until you call <code>$pool-&gt;promise()</code>, whereas requests are dispatched immediately when you call <code>$s3Client-&gt;listObjectsAsync(…)</code>. The <code>CommandPool</code> defers the initiation of calls until you explicitly tell it to do so. In addition, by default, a command pool will limit concurrency to 25 operations at a time by default, This simultaneous operation limit can be tuned according to your project’s needs. For a more complex example see <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/commands.html#commandpool">CommandPool</a> in the AWS SDK for PHP User Guide.</p> <p> With promises, waiters, and command pools, version 3 of the AWS SDK for PHP makes it easy to write asynchronous or concurrent code! We welcome your feedback.</p> Automating the Deployment of AWS Config with the AWS SDK for PHP https://aws.amazon.com/blogs/developer/automating-the-deployment-of-aws-config-with-the-aws-sdk-for-php/ Fri, 04 Dec 2015 22:58:01 +0000 9b1b4e18372206e19ad3c0c09241dfeeb83d04fa My colleague Joseph Fontes, an AWS Solutions Architect, wrote the guest post below to discuss automation strategies for AWS Config. There are times when you need to automate the deployment of services either in your account or within external accounts.&nbsp; When I recently had to enable AWS Config support in remote accounts, I approached this […] <p> My colleague <a href="https://www.linkedin.com/in/joefontes">Joseph Fontes</a>, an AWS Solutions Architect, wrote the guest post below to discuss automation strategies for AWS Config.</p> <hr /> <p> There are times when you need to automate the deployment of services either in your account or within external accounts.<span>&nbsp; </span>When I recently had to enable AWS Config support in remote accounts, I approached this task the way many others do….by opening the <a href="https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-config-2014-11-12.html">AWS SDK for PHP Reference Guide</a>!</p> <p> To complete this task, we will need three AWS Config methods: putConfigurationRecorder(), putDeliveryChannel(), and startConfigurationRecorder().<span>&nbsp; </span>Before making the call to putDeliveryChannel(), we need to create our Amazon S3 bucket destination and identify an AWS SNS topic.<span>&nbsp; </span></p> <p> Let’s instantiate the clients we will need for this exercise.<span>&nbsp; </span>The client creation will be slightly different for those familiar with creating clients in version 2 of the AWS SDK for PHP.</p> <pre class="brush: php"> $s3Client = $sdk-&gt;createS3(); $iamClient = $sdk-&gt;createIam(); $confClient = $sdk-&gt;createConfigService(); $snsClient = $sdk-&gt;createSns(); </pre> <p> Let’s next create an S3 bucket and destination for our AWS Config logs.<span>&nbsp; </span>Remember that S3 buckets must be globally unique. We cannot simply use a name like “logs.” <span>&nbsp;</span>For this reason, our naming convention will use our account number:</p> <pre class="brush: php"> $accountID = &quot;XXXXXXXXXXXX&quot;; $s3Bucket = $accountID.&quot;-config&quot;; $role = &quot;AWS-Config-Role-IAM&quot;; $s3Res = $s3Client-&gt;listBuckets([]); $s3ResA = $s3Res-&gt;toArray(); if(bucketExists($sdk,$s3Bucket,$s3ResA) == 0) { $s3Data = [ 'ACL' =&gt; 'private', 'Bucket' =&gt; $s3Bucket, 'LocationConstraint' =&gt; $region ]; $s3Res = $s3Client-&gt;createBucket($s3Data); $s3ResA = $s3Res-&gt;toArray(); print_r($s3ResA); print &quot;Waiting for bucket to become available...&quot;; $s3Client-&gt;waitUntil('BucketExists', [ 'Bucket' =&gt; $s3Bucket ]); } </pre> <p> In the preceding example, I have written a function to test if the bucket exists.<span>&nbsp; </span>This is a completely optional step. The full code will be made available for download.</p> <p> The call for createBucket() with Amazon S3 followed by the waitUntil() method delays script execution until the S3 bucket is available for use.<span>&nbsp; </span></p> <p> We now need to create the IAM role AWS Config<span> </span>uses to access<span> </span>the S3 bucket.<span>&nbsp; </span>We need an assume role policy to reference during the call.<span>&nbsp; </span>I have created a text file, policy.json, with the following contents:</p> <pre class="brush: js"> { &quot;Version&quot;: &quot;2012-10-17&quot;, &quot;Statement&quot;: [ { &quot;Sid&quot;: &quot;&quot;, &quot;Effect&quot;: &quot;Allow&quot;, &quot;Principal&quot;: { &quot;Service&quot;: &quot;config.amazonaws.com&quot; }, &quot;Action&quot;: &quot;sts:AssumeRole&quot; } ] } </pre> <p> Create a local copy of the <a href="https://gist.github.com/aws-joe/11849d2be61eb5616e3d">policy.json file</a>.</p> <p> Next, we need to create an additional policy file that gives the AWS Config service permissions to perform required tasks in your account. Download the following file and place it in your running directory:</p> <p> <a href="https://gist.github.com/aws-joe/914fcbf666867d5f360a">config-policy.json</a></p> <p> We can now create the IAM role for the AWS Config service:</p> <pre class="brush: php"> $config_topic = &quot;ConfigTopicSNS&quot;; $policy_info = file_get_contents('config-policy.json'); $replace_sns = &quot;:&quot;.$AccountID.&quot;:&quot;.$config_topic; $replS3Bucket = &quot;XXXXXXXXXXXXXXXXXXXXXXXXXXX&quot;; $replSNS = &quot;YYYYYYYYYYYYYYYYYYYYYYYYYYYYY&quot;; $replS3Bucket2 = &quot;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ&quot;; $policy_info = str_replace($replS3Bucket,$s3Bucket,$policy_info); $policy_info = str_replace($replSNS,$replace_sns,$policy_info); $policy_info = str_replace($replS3Bucket2,$s3Bucket,$policy_info); $iamData = [ 'RoleName' =&gt; $role, 'AssumeRolePolicyDocument' =&gt; file_get_contents('policy.json') ]; $iamRes = $iamClient-&gt;createRole($iamData); $iamResA = $iamRes-&gt;toArray(); $roleARN = $iamResA['Role']['Arn']; $iamData = [ 'PolicyDocument' =&gt; $policy_info, 'PolicyName' =&gt; 'NEWConfigPolicy', 'Description' =&gt; &quot;config policy via sdk&quot; ]; $iamRes = $iamClient-&gt;createPolicy($iamData); $iamResA = $iamRes-&gt;toArray(); $confPolicyArn = $iamResA['Policy']['Arn']; $iamData = [ 'PolicyArn' =&gt; $ConfPolicyArn, 'RoleName' =&gt; $Role ]; $iamRes = $iamClient-&gt;attachRolePolicy($iamData); $iamResA = $iamRes-&gt;toArray(); </pre> <p> This portion imports the trust policy defined by the local file, policy.json, along with the permissions policy identified by the local file, config-policy.json.<span>&nbsp; </span>The permissions policy is modified upon read to ensure proper identifiers are used in the script.</p> <p> Let’s create the SNS topic.</p> <pre class="brush: php"> $snsTopic = 'ConfigTopicSNS'; $snsData = ['Name' =&gt; $config_topic]; $snsRes = $snsClient-&gt;createTopic($snsData); $snsResA = $snsRes-&gt;toArray(); $snsTopicARN = $snsResA['TopicArn']; </pre> <p> We now have to call the putConfigurationRecorder() method.<span>&nbsp; </span>This creates a new configuration recorder that will identify the changes we want to record.<span>&nbsp; </span>In this example, we want to record all changes.<span>&nbsp; </span>Readers can be more prescriptive in their recordings by identifying resources types.<span>&nbsp; </span>You’ll find a list of supported resource types here:</p> <p> <a href="http://docs.aws.amazon.com/config/latest/developerguide/resource-config-reference.html#supported-resources">http://docs.aws.amazon.com/config/latest/developerguide/resource-config-reference.html#supported-resources</a></p> <pre class="brush: php"> $confData = [ 'ConfigurationRecorder' =&gt; [ 'name' =&gt; 'default', 'recordingGroup' =&gt; [ 'allSupported' =&gt; true, ], 'roleARN' =&gt; $roleARN, ], ]; $confClient-&gt;putConfigurationRecorder($confData); </pre> <p> Now that we know what we are going to record, we have to identify where we will send the recordings.<span>&nbsp; </span>The following shows the putDeliveryChannel() method, which needs the S3 bucket (created earlier) to store the recordings and the SNS topic, which will alert to configuration changes.</p> <pre class="brush: php"> $confData = [ 'DeliveryChannel' =&gt; [ 'name' =&gt; 'default', 's3BucketName' =&gt; $s3Bucket, 'snsTopicARN' =&gt; $snsTopicARN, ], ]; $confClient-&gt;putDeliveryChannel($confData); </pre> <p> Finally, now that we have our recording configuration and methods for delivery defined, we have to start recording the changes:</p> <pre class="brush: php"> $confData = ['ConfigurationRecorderName' =&gt; 'default' ]; $confClient-&gt;startConfigurationRecorder($confData); </pre> <p> Now that changes to infrastructure within this region of our account are being recorded with notifications sent, we can be notified of and record infrastructure updates.<span>&nbsp; </span>We can then use additional SNS subscriptions to process the list of items in our infrastructure that have changed, review them for root cause analysis in the event of service issues, use centralized logging along with event correlation to look for system anomalies, and so on.</p> <p> You can review the processing of Amazon SNS notifications here:</p> <p> <a href="http://blogs.aws.amazon.com/php/post/Tx15276Q7B4NUO0/Receiving-Amazon-SNS-Messages-in-PHP">http://blogs.aws.amazon.com/php/post/Tx15276Q7B4NUO0/Receiving-Amazon-SNS-Messages-in-PHP</a></p> <p> <br /> &nbsp;</p> <p> &nbsp;</p> Receiving Amazon SNS Messages in PHP https://aws.amazon.com/blogs/developer/receiving-amazon-sns-messages-in-php/ Wed, 04 Nov 2015 17:46:40 +0000 7d24b7d8c30c862cd10111a28e33572e2be6e710 A little over a year ago, we announced a new feature in the AWS SDK for PHP that allowed customers to validate inbound SNS messages. In the latest version of the SDK, this functionality is now available in its own package, one that does not depend on the SDK, so it’s simpler to listen to […] <p> A little over a year ago, we <a href="https://blogs.aws.amazon.com/php/post/Tx2G9D94IE6KPAY/Receiving-Amazon-SNS-Messages-in-PHP">announced a new feature in the AWS SDK for PHP</a> that allowed customers to validate inbound SNS messages. In the latest version of the SDK, this functionality is now available in <a href="https://packagist.org/packages/aws/aws-php-sns-message-validator">its own package</a>, one that does not depend on the SDK, so it’s simpler to listen to SNS topics with lightweight web services. In this blog post, I’ll show you how to use the Amazon SNS message validator for PHP to parse messages in a single-file web application.</p> <h2> About SNS</h2> <p> <a href="http://aws.amazon.com/sns/">Amazon Simple Notification Service</a> (Amazon SNS) is a fast and fully managed push messaging service that can deliver messages over email, SMS, mobile push, and HTTP/HTTPS endpoints.</p> <p> With Amazon SNS, you can set up <a href="http://docs.aws.amazon.com/sns/latest/dg/CreateTopic.html">topics</a> to publish custom messages to subscribed endpoints. SNS messages are used by many of the other AWS services to communicate information asynchronously about your AWS resources. Some examples include:</p> <ul> <li> Configuring <a href="http://aws.amazon.com/glacier/">Amazon Glacier</a> to notify you when a retrieval job is complete.</li> <li> Configuring <a href="http://aws.amazon.com/cloudtrail/">AWS CloudTrail</a> to notify you when a new log file has been written.</li> <li> Configuring <a href="http://aws.amazon.com/elastictranscoder/">Amazon Elastic Transcoder</a> to notify you when a transcoding job changes status (e.g., from “Progressing” to “Complete”)</li> </ul> <h2> Receiving SNS Messages and Verifying Their Signature</h2> <p> Using the <a href="https://github.com/aws/aws-php-sns-message-validator/blob/master/src/Message.php">SNS Message Validator’s <code>Message</code> class</a>, you can easily parse raw POST data from SNS:</p> <pre class="brush: php"> &lt;?php require 'path/to/vendor/autoload.php'; $message = AwsSnsMessage::fromRawPostData(); echo $message-&gt;get('Message'); </pre> <p> Amazon SNS sends different types of messages, including <code>SubscriptionConfirmation</code>, <code>Notification</code>, and <code>UnsubscribeConfirmation</code>. The formats of these messages are described in the <a href="http://docs.aws.amazon.com/sns/latest/dg/json-formats.html">Appendix: Message and JSON Formats</a> section of the Amazon SNS Developer Guide.</p> <p> Messages from Amazon SNS are signed. As a best practice, you should use the <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.Sns.MessageValidator.html"><code>MessageValidator</code></a> class to verify the signature and ensure a message was sent from Amazon SNS.</p> <pre class="brush: php"> &lt;?php use AwsSnsMessage; use AwsSnsMessageValidator; $message = Message::fromRawPostData(); // Validate the message $validator = new MessageValidator(); $validator-&gt;validate($message); </pre> <p> Instances of <code>AwsSnsMessageValidator</code> have two methods for validating messages, both of which take an instance of <code>AwsSnsMessage</code> as their only argument. <code>validate</code> (shown above) will throw an <code>AwsSnsExceptionInvalidSnsMessageException</code>. <code>isValid</code> will return a Boolean — <code>true</code> for valid messages and <code>false</code> for invalid ones.</p> <h2> Confirming a Subscription to a Topic</h2> <p> In order for an HTTP(S) endpoint to receive messages, it must first be subscribed to an SNS topic. Subscriptions are confirmed over HTTP(S), so you’ll need to create and deploy an endpoint before you set up a subscription. <code>SubscriptionConfirmation</code> messages provide a URL you can use to confirm the subscription.</p> <pre class="brush: php"> $message = AwsSnsMessage::fromRawPostData(); // Validate the message $validator = new MessageValidator(); if ($validator-&gt;isValid($message)) { file_get_contents($message-&gt;get('SubscribeURL')); } </pre> <h2> Handling Notifications</h2> <p> Let’s put it all together and add some extra code for handling both notifications and subscription control messages.</p> <pre class="brush: php"> &lt;?php if ('POST' !== $_SERVER['REQUEST_METHOD']) { http_response_code(405); die; } require 'path/to/vendor/autoload.php'; try { $message = AwsSnsMessage::fromRawPostData(); $validator = new AwsSnsMessageValidator(); $validator-&gt;validate($message); if (in_array($message['Type'], ['SubscriptionConfirmation', 'UnsubscribeConfirmation']) { file_get_contents($message['SubscribeURL']); } $log = new SplFileObject('../messages.log', 'a'); $log-&gt;fwrite($message['Message'] . &quot;n&quot;); } catch (Exception $e) { http_response_code(404); die; } </pre> <h2> Conclusion</h2> <p> As you can see, receiving, verifying, and handling Amazon SNS messages is simple. Setting up your application to receive SNS messages will allow you to create applications that can handle asynchronous communication from AWS services and other parts of your application.</p> AWS Workshop and Hackathon at PNWPHP https://aws.amazon.com/blogs/developer/aws-workshop-and-hackathon-at-pnwphp/ Thu, 06 Aug 2015 21:11:28 +0000 9a32d66f4e126b6906bdcabd58d9de946fcc3879 In September, the Pacific Northwest PHP Conference (PNWPHP) is happening in Seattle. It’s just down the street from us, and we decided to partner with the them to host an AWS Workshop and Hackathon on September 10th, 2015. The workshop portion will serve as kind of AWS bootcamp for PHP developers, and will include a […] <p> In September, the <a href="http://pnwphp.com">Pacific Northwest PHP Conference</a> (PNWPHP) is happening in Seattle. It’s just down the street from us, and we decided to partner with the them to host an <a href="http://pnwphp.com/events-hackathon">AWS Workshop and Hackathon</a> on September 10th, 2015.</p> <p> The workshop portion will serve as kind of AWS bootcamp for PHP developers, and will include a few presentations about AWS services and architecture, the <a href="https://github.com/aws/aws-sdk-php">AWS SDK for PHP</a>, and running PHP applications on AWS. You can see a full list of the presentations and speakers on the PNWPHP website.</p> <p> The hackathon portion will allow people to team up and create something using AWS services and the SDK. Like most hackathons, there will be food and prizes involved. Hackathon participants will also receive AWS credits through the <a href="https://aws.amazon.com/activate/">AWS Activate</a> program to cover the costs of the services they will be using during the hackathon.</p> <p> Tickets for AWS Workshop and Hackathon are sold separately from the main PNWPHP conference, so whether you end up attending the main conference or not, you still have the opportunity to join us at our workshop/hackathon. In fact, you can use the discount code &quot;<strong>AWSHACK</strong>&quot; to get your AWS Workshop and Hackathon ticket for a 50% discount. Head to the <a href="https://pnwphp2015.busyconf.com/bookings/new">PNWPHP registration page</a> to get your ticket.</p> <p> Whether you are a Seattle native, or you are in town for PNWPHP, we hope to see you at our special AWS Workshop and Hackathon.</p> Reduce Composer Issues on Elastic Beanstalk https://aws.amazon.com/blogs/developer/reduce-composer-issues-on-elastic-beanstalk/ Mon, 06 Jul 2015 20:49:47 +0000 2398c609df222b9bb31dddc88961f90c39c23eb6 During the past couple of months, we’ve had a few reports from customers where they have experienced PHP application deployment failures on AWS Elastic Beanstalk related to parsing exceptions being thrown by Composer. In case you have recently run into the issue yourself, we would like to briefly describe why it is happening and how […] <p> During the past couple of months, we’ve had a few reports from customers where they have experienced PHP application deployment failures on <a href="http://aws.amazon.com/elasticbeanstalk/">AWS Elastic Beanstalk</a> related to parsing exceptions being thrown by Composer. In case you have recently run into the issue yourself, we would like to briefly describe why it is happening and how you can circumvent the issue.</p> <h2> The issue</h2> <p> The issue occurs when a project or its dependencies expresses its requirements using newer Composer syntax features like the carat (<code>^</code>) operator. For users of the AWS SDK for PHP, the error looks something like this:</p> <pre> [RuntimeException] Could not load package aws/aws-sdk-php in http://packagist.org: [UnexpectedValueException] Could not parse version constraint ^5.3: Invalid version string &quot;^5.3&quot; </pre> <p> We also observed the issue with some versions of the Laravel framework and a few other libraries. The issue comes up when you are using older Elastic Beanstalk stacks with your applications. The older stacks have an old version of Composer included on the underlying Amazon Machine Image (AMI) that does not support some of the latest Composer features like the carat (<code>^</code>) and new OR (<code>||</code>) syntax.</p> <h2> The solution</h2> <p> There are 3 different ways to solve this issue.</p> <ol> <li> <strong>Upgrade your application to use the latest Elastic Beanstalk solution stack.</strong> The latest solution stacks for PHP have a more recent version of Composer that supports the new syntax features.</li> <li> <strong>Use Elastic Beanstalk configuration files (<code>.ebextension</code>).</strong> You can create a file ending in <code>.config</code> inside your <code>.ebextension</code> directory that allows you to perform a Compose <code>self-update</code> command before installing your dependencies. For example, name the file <code>01composer.config</code> and add the following configuration:<p></p> <pre> commands: 01updateComposer: command: export COMPOSER_HOME=/root &amp;&amp; /usr/bin/composer.phar self-update option_settings: - namespace: aws:elasticbeanstalk:application:environment option_name: COMPOSER_HOME value: /root</pre> </li> <li> <strong>Install your dependencies locally.</strong> One way to avoid issues with Composer during deployment is to bypass the whole Composer workflow entirely by creating deployments of your application with the dependencies pre-installed.</li> </ol> <h2> The conclusion</h2> <p> We hope that this short blog post will be helpful if you happen to run into this issue. If this article does not solve your problem or you are running into other issues, please contact AWS Support or ask for help on the <a href="https://forums.aws.amazon.com/forum.jspa?forumID=86">Elastic Beanstalk forum</a>.</p> AWS SDK for PHP Office Hour https://aws.amazon.com/blogs/developer/aws-sdk-for-php-office-hour/ Wed, 24 Jun 2015 22:15:16 +0000 d03e73e06dc1d3694125f663bd2bb03f4f78915a The AWS SDKs and Tools team invites you to the first-ever online office hour hosted by the maintainers of the AWS SDK for PHP. It will be held via Google Hangouts at 10:30-11:30am PDT (UTC -7:00) on Monday 6/29. If you don’t have one already, you will need to create an account with Google to […] <p> The AWS SDKs and Tools team invites you to the first-ever online office hour hosted by the maintainers of the AWS SDK for PHP. It will be held via Google Hangouts at <strong>10:30-11:30am PDT (UTC -7:00) on Monday 6/29</strong>. If you don’t have one already, you will need to create an account with Google to join the video chat.</p> <p> This first office hour will be driven by customer questions. We expect to focus on questions about the SDK, but any questions related to PHP development on AWS are welcome. We’re excited to meet you and help you be successful in developing PHP applications on AWS!</p> <p> Please <a href="https://www.eventbrite.com/e/aws-sdk-for-php-office-hour-tickets-17517303727">register for the event</a>, add it to your calendar, and join the office hour next Monday.</p> Updated Framework Modules for V3 https://aws.amazon.com/blogs/developer/updated-framework-modules-for-v3/ Wed, 24 Jun 2015 18:22:48 +0000 bf3a1fcbc6d98cc7b29b1600c5bef72190ed54f1 Last month, we announced that Version 3 of the AWS SDK for PHP was generally available. We’ve now updated all of our framework-specific modules with releases that support Version 3 (V3) of the SDK. Take a look! AWS Service Provider for Laravel V3 Support: Version 3.0.0 Older Versions: 2.0 branch – For Version 2 of […] <p> Last month, we announced that <a href="http://blogs.aws.amazon.com/php/post/Tx29HZZVCASVU21/Version-3-of-the-AWS-SDK-for-PHP">Version 3 of the AWS SDK for PHP was generally available</a>. We’ve now updated all of our framework-specific modules with releases that support Version 3 (V3) of the SDK. Take a look!</p> <ul> <li> <a href="https://github.com/aws/aws-sdk-php-laravel">AWS Service Provider for Laravel</a><p></p> <ul> <li> V3 Support: <a href="https://github.com/aws/aws-sdk-php-laravel/releases/tag/3.0.0">Version 3.0.0</a></li> <li> Older Versions:<p></p> <ul> <li> <a href="https://github.com/aws/aws-sdk-php-laravel/tree/2.0">2.0 branch</a> – For Version 2 of the AWS SDK for PHP and Laravel 5</li> <li> <a href="https://github.com/aws/aws-sdk-php-laravel/tree/1.0">1.0 branch</a> – For Version 2 of the AWS SDK for PHP and Laravel 4</li> </ul> </li> </ul> </li> <li> <a href="https://github.com/aws/aws-sdk-php-zf2">AWS SDK ZF2 Module</a><p></p> <ul> <li> V3 Support: <a href="https://github.com/aws/aws-sdk-php-zf2/releases/tag/2.0.0">Version 2.0.0</a></li> <li> Older Versions:<p></p> <ul> <li> <a href="https://github.com/aws/aws-sdk-php-zf2/tree/1.2">1.2 branch</a> – For Version 2 of the AWS SDK for PHP</li> </ul> </li> </ul> </li> <li> <a href="https://github.com/aws/aws-sdk-php-silex">AWS Service Provider for Silex</a><p></p> <ul> <li> V3 Support: <a href="https://github.com/aws/aws-sdk-php-silex/releases/tag/2.0.1">Version 2.0.1</a></li> <li> Older Versions:<p></p> <ul> <li> <a href="https://github.com/aws/aws-sdk-php-silex/tree/1.1">1.1. branch</a> – For Version 2 of the AWS SDK for PHP</li> </ul> </li> </ul> </li> </ul> <p> We’ve also updated our <a href="https://github.com/awslabs/aws-sdk-php-resources">AWS Resource APIs for PHP</a> library which we <a href="http://blogs.aws.amazon.com/php/post/Tx3K1TS5GUKJR85/Preview-the-AWS-Resource-APIs-for-PHP">previewed in December</a>. Now that V3 of the SDK is stable, we will be working on adding features and documentation to this library over the coming weeks.</p> <p> As always, we appreciate your feedback on any of our open source packages. Check out these updates and let us know what you think. :-)</p> <p> <em>P.S. We’d like to give a special thanks to <a href="https://twitter.com/GrahamJCampbell">Graham Campbell</a> and <a href="https://twitter.com/mic_gallego">Micha&euml;l Gallego</a> for their contributions to the Laravel and ZF2 packages, respectively.</em></p> HaPHPy 20th Birthday to PHP https://aws.amazon.com/blogs/developer/haphpy-20th-birthday-to-php/ Mon, 08 Jun 2015 17:22:10 +0000 0d3dd4355c5a596bc5fad6217efe11a67c09bfd7 Twenty years ago, Rasmus Lerdorf announced version 1.0 of PHP. It’s now two decades later, and PHP has evolved so much and is still going strong. The AWS SDK for PHP team would like to say thank you to everyone who has contributed to the PHP language and community over these past twenty years, and […] <p> Twenty years ago, <a href="https://groups.google.com/forum/#!msg/comp.infosystems.www.authoring.cgi/PyJ25gZ6z7A/M9FkTUVDfcwJ">Rasmus Lerdorf announced version 1.0 of PHP</a>. It’s now two decades later, and PHP has evolved so much and is still going strong. The <a href="https://github.com/aws/aws-sdk-php">AWS SDK for PHP</a> team would like to say thank you to everyone who has contributed to the PHP language and community over these past twenty years, and wish PHP a very <em>HaPHPy</em> birthday.</p> <p> Join in the celebration today by reflecting on the <a href="https://line.do/ww/php-evolution/8oq/vertical">history of PHP</a>, following the <a href="https://twitter.com/hashtag/20yearsofphp">#20yearsofphp</a> hashtag, and checking out some of these other blog posts from people in the PHP community:</p> <ul> <li> <a href="http://benramsey.com/blog/2015/06/20-years-of-php/">20 Years of PHP</a> by Ben Ramsey</li> <li> <a href="http://littlehart.net/atthekeyboard/2015/06/08/php-created-this-monster/">PHP Created this Monster</a> by Chris Hartjes</li> <li> <a href="http://daveyshafik.com/archives/69164-celebrating-20-years-of-php.html">Celebrating 20 Years of PHP</a> by Davey Shafik</li> <li> <a href="http://www.erikaheidi.com/blog/celebrating-php-twenty-years">Celebrating Twenty Years of PHP</a> by Erika Heidi</li> <li> <a href="http://blog.calevans.com/2015/06/08/celebrating-20-years-of-php/">Celebrating 20 Years of PHP</a> by Cal Evans</li> </ul> Version 3 of the AWS SDK for PHP https://aws.amazon.com/blogs/developer/version-3-of-the-aws-sdk-for-php/ Wed, 27 May 2015 20:15:53 +0000 d5ec99c4442a7c3239a82b2dc7881b6513d42f92 Last October, we announced the Developer Preview of Version 3 of the AWS SDK for PHP. We even presented about it at AWS re:Invent last November. We are grateful for your early feedback and support. Since last fall, we’ve been hard at work on improving, testing, and documenting Version 3 to get it ready for […] <p> Last October, we <a href="http://blogs.aws.amazon.com/php/post/Tx3RR28K9AAHPD1/Version-3-Preview-of-the-AWS-SDK">announced the Developer Preview of Version 3 of the AWS SDK for PHP</a>. We even <a href="http://www.slideshare.net/AmazonWebServices/dev305-building-apps-with-the-aws-sdk-for-php-aws-reinvent-2014-41529323">presented about it at AWS re:Invent</a> last November. We are grateful for your early feedback and support. Since last fall, we’ve been hard at work on improving, testing, and documenting Version 3 to get it ready for a stable release. We’re excited to announce that <a href="https://github.com/aws/aws-sdk-php/releases/tag/3.0.0">Version 3 of the AWS SDK for PHP</a> is now generally available <a href="https://packagist.org/packages/aws/aws-sdk-php">via Composer</a> and <a href="https://github.com/aws/aws-sdk-php">on GitHub</a>.</p> <p> Version 3 of the SDK (V3) represents a significant effort to improve the capabilities of the SDK, incorporate over two years of customer feedback, upgrade our dependencies, improve performance, and adopt the latest PHP standards.</p> <h2> What we’re excited about</h2> <p> We’ve made many improvements to V3, even since our <a href="http://blogs.aws.amazon.com/php/post/Tx3RR28K9AAHPD1/Version-3-Preview-of-the-AWS-SDK">blog post about the Developer Preview</a> (check out that post if you haven’t already). There are also some things that have changed or have been removed since Version 2 of the SDK (V2). We encourage you to take a look at our <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/migration.html">V3 Migration Guide</a> for all the details about what has changed.</p> <p> V3 has less code and better performance than V2 and is using the latest version of the <a href="http://docs.guzzlephp.org/en/latest/">Guzzle HTTP library</a>. It also has some exciting new features and improvements.</p> <h3> Asynchronous requests and promises</h3> <p> V3 allows you to execute operations asynchronously. This not only means that it is easier to do concurrent requests, it’s also easier to create asynchronous and cooperative workflows. We use <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/promises.html">Promises</a>, the basic building block of our asynchronous features, all throughout the SDK’s core. We also use them to implement the higher-level abstractions SDK, including <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/commands.html#commandpool">Command Pools</a>, <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/paginators.html">Paginators</a>, <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/waiters.html">Waiters</a>, and service-specific features like the <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/guide/service/s3-multipart-upload.html">S3 MultipartUploader</a>. That means that almost every feature of the SDK can be used in an asynchronous way.</p> <p> To execute an operation asynchronously, you simply add &quot;Async&quot; as a suffix to your method call.</p> <pre class="brush: php;"> // The SYNCHRONOUS (normal) way: // Executing an operation returns a Result object. $result = $s3Client-&gt;putObject([ 'Bucket' =&gt; 'your-bucket', 'Key' =&gt; 'docs/file.pdf', 'Body' =&gt; fopen('/path/to/file.pdf', 'r'), ]); // You can access the result data from the Result object. echo $result['ObjectURL']; // The ASYNCHRONOUS way: // Executing an operation asynchronously returns a Promise object. $promise = $s3Client-&gt;putObjectAsync([ 'Bucket' =&gt; 'your-bucket', 'Key' =&gt; 'docs/file.pdf', 'Body' =&gt; fopen('/path/to/file.pdf', 'r'), ]); // Wait for the operation to complete to get the Result object. $result = $promise-&gt;wait(); // Then you can access the result data like normal. echo $result['ObjectURL']; </pre> <p> The true power of using asynchronous requests is being able to create asynchronous workflows. For example, if you wanted to create a DynamoDB table, wait until it is ACTIVE (using <em>Waiters</em>), and then write some data to it, you can use the <code>then()</code> method of the <code>Promise</code> object to chain those actions together.</p> <pre class="brush: php;"> $client-&gt;createTableAsync([ 'TableName' =&gt; $table, // Other params... ])-&gt;then(function () use ($client, $table) { return $client-&gt;getWaiter('TableExists', [ 'TableName' =&gt; $table, ])-&gt;promise(); })-&gt;then(function () use ($client, $table) { return $client-&gt;putItemAsync([ 'TableName' =&gt; $table, 'Item' =&gt; [ // Item attributes... ] ]); })-&gt;wait(); </pre> <p> Please take a look at our <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/promises.html">detailed guide on promises</a> for more information.</p> <h3> PSR-7 compliance and decoupling of the HTTP layer</h3> <p> The <a href="http://www.php-fig.org/">PHP-FIG</a> has recently announced the acceptance of <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md">PSR-7</a>, a &quot;PHP Standard Recommendation&quot; that defines interfaces for HTTP messages (e.g., Request and Response objects). We have adopted these interfaces for how we represent HTTP requests within the SDK, and it has allowed us to decouple the SDK from Guzzle such that V3 will work with both <a href="http://docs.guzzlephp.org/en/5.3/">Guzzle 5</a> and <a href="http://docs.guzzlephp.org/en/latest/">Guzzle 6</a>. It’s also possible to write your own HTTP handler for the SDK that does not use Guzzle.</p> <p> The SDK defaults to using Guzzle 6 to perform HTTP requests. Guzzle 6 comes with a number of improvements, including support for asynchronous requests, PSR-7 compliance, and swappable HTTP adapters (including a PHP stream wrapper implementation that can be used on systems where cURL is not available).</p> <h3> JMESPath querying of results and paginators</h3> <p> In V3, the <code>Result</code> object has a new method: <code>search()</code>. With this method you can query data in <code>Result</code> objects using JMESPath expressions. <a href="http://jmespath.org/">JMESPath</a> is a query language for JSON, or, in our case, PHP arrays.</p> <pre class="brush: php;"> $result = $ec2Client-&gt;describeInstances(); print_r($result-&gt;search('Reservations[].Instances[].InstanceId')); </pre> <p> JMESPath expressions can also be applied to <em>Paginators</em> in the same way. This will return a new <code>Iterator</code> that yields the result of the expression on every page of data.</p> <pre class="brush: php;"> $results = $s3-&gt;getPaginator('ListObjects', [ 'Bucket' =&gt; 'my-bucket', ]); foreach ($results-&gt;search('Contents[].Key') as $key) { echo $key . &quot;n&quot;; } </pre> <h2> Time to code</h2> <p> We hope you will enjoy using Version 3 of the AWS SDK for PHP. Here are the links you need to get started:</p> <ul> <li> <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/guide">User Guide Documentation</a></li> <li> <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/api">API Documentation</a></li> <li> <a href="https://github.com/aws/aws-sdk-php">GitHub Repository</a></li> <li> Follow <a href="https://twitter.com/awsforphp">@awsforphp</a> on Twitter</li> </ul> DynamoDB JSON and Array Marshaling for PHP https://aws.amazon.com/blogs/developer/dynamodb-json-and-array-marshaling-for-php/ Tue, 03 Feb 2015 16:04:18 +0000 2e80c138ef466560878ec17555188a88ff75785b Back in October of 2014, Amazon DynamoDB added support for new data types, including the map (M) and list (L) types. These new types, along with some API updates, make it possible to store more complex, multilevel data, and use DynamoDB for document storage. The DynamoDB Marshaler To make these new types even easier for […] <p> Back in October of 2014, Amazon DynamoDB added support for new data types, including the map (<code>M</code>) and list (<code>L</code>) types. These new types, along with some API updates, make it possible to store more complex, multilevel data, and use DynamoDB for document storage.</p> <h2> The DynamoDB Marshaler</h2> <p> To make these new types even easier for our PHP SDK users, we added a new class, called the <a href="http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.DynamoDb.Marshaler.html">DynamoDB Marshaler</a>, in Version 2.7.7 of the <a href="https://github.com/aws/aws-sdk-php">AWS SDK for PHP</a>. The Marshaler object has methods for marshaling JSON documents and PHP arrays to the DynamoDB item format and unmarshaling them back.</p> <h3> Marshaling a JSON Document</h3> <p> Let’s say you have JSON document describing a contact in the following format:</p> <pre> { &quot;id&quot;: &quot;5432c69300594&quot;, &quot;name&quot;: { &quot;first&quot;: &quot;Jeremy&quot;, &quot;middle&quot;: &quot;C&quot;, &quot;last&quot;: &quot;Lindblom&quot; }, &quot;age&quot;: 30, &quot;phone_numbers&quot;: [ { &quot;type&quot;: &quot;mobile&quot;, &quot;number&quot;: &quot;5555555555&quot;, &quot;preferred&quot;: true }, { &quot;type&quot;: &quot;home&quot;, &quot;number&quot;: &quot;5555555556&quot;, &quot;preferred&quot;: false } ] } </pre> <p> You can use the DynamoDB Marshaler to convert this JSON document into the format required by DynamoDB.</p> <pre class="brush: php;"> use AwsDynamoDbDynamoDbClient; use AwsDynamoDbMarshaler; $client = DynamoDbClient::factory(/* your config */); $marshaler = new Marshaler(); $json = file_get_contents('/path/to/your/document.json'); $client-&gt;putItem([ 'TableName' =&gt; 'YourTable', 'Item' =&gt; $marshaler-&gt;marshalJson($json) ]); </pre> <p> The output of <code>marshalJson()</code> is an associative array that includes all the type information required for the DynamoDB <code>'Item'</code> parameter.</p> <pre class="brush: php;"> [ 'id' =&gt; ['S' =&gt; '5432c69300594'], 'name' =&gt; ['M' =&gt; [ 'first' =&gt; ['S' =&gt; 'Jeremy'], 'middle' =&gt; ['S' =&gt; 'C'], 'last' =&gt; ['S' =&gt; 'Lindblom'], ]], 'age' =&gt; ['N' =&gt; '30'], 'phone_numbers' =&gt; ['L' =&gt; [ ['M' =&gt; [ 'type' =&gt; ['S' =&gt; 'mobile'], 'number' =&gt; ['S' =&gt; '5555555555'] ]], ['M' =&gt; [ 'type' =&gt; ['S' =&gt; 'home'], 'number' =&gt; ['S' =&gt; '5555555556'] ]], ]], ]; </pre> <p> To retrieve an item and get the JSON document back, you need to use the <code>unmarshalJson()</code> method.</p> <pre class="brush: php;"> $result = $client-&gt;getItem([ 'TableName' =&gt; 'YourTable', 'Key' =&gt; ['id' =&gt; ['S' =&gt; '5432c69300594']] ]); $json = $marshaler-&gt;unmarshalJson($result['Item']); </pre> <h3> Marshaling a Native PHP Array</h3> <p> The <code>Marshaler</code> also provides the <code>marshalItem()</code> and <code>unmarshalItem()</code> methods that do the same type of thing, but for arrays. This is essentially an upgraded version of the existing <code>DynamoDbClient::formatAttributes()</code> method.</p> <pre class="brush: php;"> $data = [ 'id' =&gt; '5432c69300594', 'name' =&gt; [ 'first' =&gt; 'Jeremy', 'middle' =&gt; 'C', 'last' =&gt; 'Lindblom', ], 'age' =&gt; 30, 'phone_numbers' =&gt; [ [ 'type' =&gt; 'mobile', 'number' =&gt; '5555555555', 'preferred' =&gt; true ], [ 'type' =&gt; 'home', 'number' =&gt; '5555555556', 'preferred' =&gt; false ], ], ]; // Marshaling the data and putting an item. $client-&gt;putItem([ 'TableName' =&gt; 'YourTable', 'Item' =&gt; $marshaler-&gt;marshalItem($data) ]); // Getting and item and unmarshaling the data. $result = $client-&gt;getItem([ 'TableName' =&gt; 'YourTable', 'Key' =&gt; ['id' =&gt; ['S' =&gt; '5432c69300594']] ]); $data = $marshaler-&gt;unmarshalItem($result['Item']); </pre> <p> Be aware that <code>marshalItem()</code> does not support binary (<code>B</code>) and set (<code>SS</code>, <code>NS</code>, and <code>BS</code>) types. This is because they are ambiguous with the string (<code>S</code>) and list (<code>L</code>) types and have no equivalent type in JSON. We are working on some ideas that will provide more help with these types in Version 3 of the SDK.</p> <h2> Deprecations in the SDK</h2> <p> The new data types are a great addition to the Amazon DynamoDB service, but one consequence of adding support for these types is that we had to deprecate the following classes and methods in the <code>AwsDynamoDb</code> namespace of the PHP SDK:</p> <ul> <li> <a href="https://github.com/aws/aws-sdk-php/blob/144d1c70e326a5dc83a325790d1b760acb1c2fbd/src/Aws/DynamoDb/DynamoDbClient.php#L130-L143"><code>AwsDynamoDbDynamoDbClient::formatValue()</code></a></li> <li> <a href="https://github.com/aws/aws-sdk-php/blob/144d1c70e326a5dc83a325790d1b760acb1c2fbd/src/Aws/DynamoDb/DynamoDbClient.php#L145-L164"><code>AwsDynamoDbDynamoDbClient::formatAttributes()</code></a></li> <li> <a href="https://github.com/aws/aws-sdk-php/blob/144d1c70e326a5dc83a325790d1b760acb1c2fbd/src/Aws/DynamoDb/Model/Attribute.php"><code>AwsDynamoDbDynamoDbClientModelAttribute</code></a></li> <li> <a href="https://github.com/aws/aws-sdk-php/blob/144d1c70e326a5dc83a325790d1b760acb1c2fbd/src/Aws/DynamoDb/Model/Item.php"><code>AwsDynamoDbDynamoDbClientModelItem</code></a></li> <li> <a href="https://github.com/aws/aws-sdk-php/blob/144d1c70e326a5dc83a325790d1b760acb1c2fbd/src/Aws/DynamoDb/Iterator/ItemIterator.php"><code>AwsDynamoDbDynamoDbClientIteratorItemIterator</code></a></li> </ul> <p> These classes and methods made assumptions about how certain native PHP types convert to DynamoDB types. The addition of the new types to DynamoDB invalidated those assumptions, and we could not update the code in a backward-compatible way to support the new types. They still work fine, but just not with the new types. These classes and methods are removed in Version 3 of the SDK, and the DynamoDB Marshaler object is meant to be the replacement for their functionality.</p> <h2> Feedback</h2> <p> We hope that this addition to the SDK makes working with DynamoDB really easy. If you have any feedback about the Marshaler or any ideas on how we can improve it, please let us know <a href="https://github.com/aws/aws-sdk-php/issues">on GitHub</a>. Better yet, send us a pull request. :-)</p> WordPress on AWS Whitepapers https://aws.amazon.com/blogs/developer/wordpress-on-aws-whitepapers/ Tue, 27 Jan 2015 18:26:42 +0000 8473f2c1aba6bbf319e194499c4675c20655d48b This is a guest post by Andreas Chatzakis (@achatzakis), one of our AWS Solutions Architects. WordPress is a very popular open source blogging tool and content management system (CMS) based on PHP and MySQL. AWS customers have been deploying WordPress to power anything from small blogs up to high traffic web sites. We have recently […] <p> This is a guest post by Andreas Chatzakis (<a href="https://twitter.com/achatzakis">@achatzakis</a>), one of our AWS Solutions Architects.</p> <hr /> <p> WordPress is a very popular open source blogging tool and content management system (CMS) based on PHP and MySQL. AWS customers have been deploying WordPress to power anything from small blogs up to high traffic web sites.</p> <p> We have recently published two new <a href="http://aws.amazon.com/whitepapers/">whitepapers</a> about running WordPress on AWS:</p> <ol> <li> <p> <a href="http://d0.awsstatic.com/whitepapers/wordpress-best-practices-on-aws.pdf">WordPress: Best Practices on AWS</a> – This whitepaper helps system administrators get started with WordPress on AWS and shows them how to improve the cost efficiency of the deployment as well as the end-user experience. It also provides a reference architecture that addresses common scalability and high availability requirements.</p> </li> <li> <p> <a href="http://d0.awsstatic.com/whitepapers/deploying-wordpress-with-aws-elastic-beanstalk.pdf">Deploying WordPress with AWS Elastic Beanstalk</a> – This whitepaper demonstrates how to use AWS Elastic Beanstalk to implement a highly available and scalable deployment of WordPress. It includes the use of additional services such as Amazon Simple Storage Service (S3), Amazon CloudFront, and Amazon ElastiCache to improve the efficiency and performance of the installation.</p> </li> </ol> <p> These whitepapers complement the slides presented at the AWS reInvent 2014 conference: <em>Best Practices for Running WordPress on AWS</em> (<a href="http://www.slideshare.net/AmazonWebServices/web302-best-practices-for-running-wordpress-on-aws-aws-reinvent-2014">slides</a>, <a href="https://www.youtube.com/user/AmazonWebServices/Cloud?x=us-en_reinvent20142_3864_181">video</a>).</p> <p> We hope you find the above material useful, and we are always eager to hear your stories and experience with WordPress on AWS!</p> Preview the AWS Resource APIs for PHP https://aws.amazon.com/blogs/developer/preview-the-aws-resource-apis-for-php/ Tue, 30 Dec 2014 21:09:58 +0000 3656f1fc069e060cbcc56503bbc241dbedc05e3b This year is just about over, but we are too excited to wait until the new year to share with you a feature we are developing for the AWS SDK for PHP. We are calling it the AWS Resource APIs for PHP. This feature is maintained as a separate package, but it acts as an […] <p> This year is just about over, but we are too excited to wait until the new year to share with you a feature we are developing for the AWS SDK for PHP. We are calling it the <em>AWS Resource APIs for PHP</em>. This feature is maintained as a <a href="https://github.com/awslabs/aws-sdk-php-resources">separate package</a>, but it acts as an extension to <a href="https://github.com/aws/aws-sdk-php/tree/v3">Version 3 of the AWS SDK for PHP</a>.</p> <p> As you know, the <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/api/index.html">core SDK</a> is composed of service client objects that have methods corresponding 1-to-1 with operations in the service’s API (e.g., <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/api/Aws/Ec2/ec2-2014-06-15.html#runinstances"><code>Ec2Client::runInstances()</code> method</a> maps to the <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html">EC2 service’s RunInstances operation</a>). The resource APIs build upon the SDK to add new types of objects that allow you to interact with the AWS service APIs in a more resource-oriented way. This allows you to use a more expressive syntax when working with AWS services, because you are acting on objects that understand their relationships with other resources and that encapsulate their identifying information.</p> <h2> Resource Objects</h2> <p> Resource objects each represent a single, identifiable AWS resource (e.g., an Amazon S3 bucket or an Amazon SQS queue). They contain information about how to identify the resource and load its data, the actions that can be performed on it, and the other resources to which it is related. Let’s take a look at a few examples showing how to interact with these resource objects.</p> <p> First, let’s set up the <code>Aws</code> object, which acts as the starting point into the resource APIs.</p> <pre class="brush: php;"> &lt;?php require 'vendor/autoload.php'; use AwsResourceAws; $aws = new Aws([ 'region' =&gt; 'us-west-2', 'version' =&gt; 'latest', 'profile' =&gt; 'your-credential-profile', ]); </pre> <p> (Note: The array of configuration options provided in the preceding example is the same as what you would provide when instantiating the <code>AwsSdk</code> object in the core SDK.)</p> <p> You can access related resources by calling the related resource’s name as a method and passing in its identity.</p> <pre class="brush: php;"> $bucket = $aws-&gt;s3-&gt;bucket('your-bucket'); $object = $bucket-&gt;object('image/bird.jpg'); </pre> <p> Accessing resources this way is evaluated lazily, so the preceding example does not actually make any API calls.</p> <p> Once you access the data of a resource, an API call will be triggered to &quot;load&quot; the resource and fetch its data. To access a resource object’s data, you can access it like an array.</p> <pre class="brush: php;"> echo $object['LastModified']; </pre> <h2> Performing Actions</h2> <p> You can perform actions on a resource by calling verb-like methods on the object.</p> <pre class="brush: php;"> // Create a bucket and object. $bucket = $aws-&gt;s3-&gt;createBucket([ 'Bucket' =&gt; 'my-new-bucket' ]); $object = $bucket-&gt;putObject([ 'Key' =&gt; 'images/image001.jpg', 'Body' =&gt; fopen('/path/to/image.jpg', 'r'), ]); // Delete the bucket and object. $object-&gt;delete(); $bucket-&gt;delete(); </pre> <p> Because the resource’s identity is encapsulated within the resource object, you never have to specify it again once the object is created. This way, actions like <code>$object-&gt;delete()</code> do not need to require arguments.</p> <h2> Collections</h2> <p> Some resources have a &quot;has many&quot; type relationship with other resources. For example, an S3 bucket has many S3 objects. The AWS Resource APIs also allow you to work with resource collections.</p> <pre class="brush: php;"> foreach ($bucket-&gt;objects() as $object) { echo $object-&gt;delete(); } </pre> <h2> Using the Resource APIs</h2> <p> We are currently working on providing API documentation for the AWS Resource APIs. Even without documentation, you can programmatically determine what methods are available on a resource object by calling the <code>respondsTo</code> method.</p> <pre class="brush: php;"> print_r($bucket-&gt;respondsTo()); // Array // ( // [0] =&gt; create // [1] =&gt; delete // [2] =&gt; deleteObjects // [3] =&gt; putObject // [4] =&gt; multipartUploads // [5] =&gt; objectVersions // [6] =&gt; objects // [7] =&gt; bucketAcl // [8] =&gt; bucketCors // [9] =&gt; bucketLifecycle // [10] =&gt; bucketLogging // [11] =&gt; bucketPolicy // [12] =&gt; bucketNotification // [13] =&gt; bucketRequestPayment // [14] =&gt; bucketTagging // [15] =&gt; bucketVersioning // [16] =&gt; bucketWebsite // [17] =&gt; object // ) var_dump($bucket-&gt;respondsTo('putObject')); // bool(true) </pre> <h2> Check it Out!</h2> <p> To get started, you can install the AWS Resource APIs for PHP using <a href="https://getcomposer.org/">Composer</a>, by requiring the <a href="https://packagist.org/packages/aws/aws-sdk-php-resources">aws/aws-sdk-php-resources package</a> in your project. The source code and README, are located in the <a href="https://github.com/awslabs/aws-sdk-php-resources">awslabs/aws-sdk-php-resources</a> repo on GitHub.</p> <p> The <a href="https://github.com/awslabs/aws-sdk-php-resources/releases/tag/0.1.0">initial preview release</a> of the AWS Resource APIs supports the following services: Amazon EC2, Amazon Glacier, Amazon S3, Amazon SNS, Amazon SQS, AWS CloudFormation, and AWS Identity and Access Management (IAM). We will continue to add support for more APIs over this next year.</p> <p> We’re eager to hear your feedback about this new feature! Please use the <a href="https://github.com/awslabs/aws-sdk-php-resources/issues">issue tracker</a> to ask questions, provide feedback, or submit any issues or feature requests.</p> AWS re:Invent 2014 https://aws.amazon.com/blogs/developer/aws-reinvent-2014/ Wed, 19 Nov 2014 21:40:21 +0000 44adc62f8cb53682fcb2dfb07658be1ae650120d We spent the past week at AWS re:Invent! The PHP SDK team was there with many of our co-workers and customers. It was a great conference, and we had a lot of fun. If you did not attend re:Invent or follow our @awsforphp Twitter feed during the event, then you have a lot to catch […] <p> We spent the past week at <a href="https://reinvent.awsevents.com/">AWS re:Invent</a>! The PHP SDK team was there with many of our co-workers and customers. It was a great conference, and we had a lot of fun.</p> <p> If you did not attend re:Invent or follow our <a href="https://twitter.com/awsforphp">@awsforphp</a> Twitter feed during the event, then you have a lot to catch up on.</p> <h2> New AWS Services and Features</h2> <p> Several new services were announced during the keynotes, on both the <a href="https://www.youtube.com/user/AmazonWebServices/Cloud?x=us-en_reinvent20142_3732_158">first day</a> and <a href="https://www.youtube.com/user/AmazonWebServices/Cloud?x=us-en_reinvent20142_3741_158">second day</a>, and during other parts of the event.</p> <p> During the first keynote, three new AWS services for code management and deployment were announced: <a href="https://aws.amazon.com/blogs/aws/code-management-and-deployment/">AWS CodeDeploy, AWS CodeCommit, and AWS CodePipeline</a>. <a href="http://aws.amazon.com/codedeploy/">CodeDeploy</a> is available today, and can help you automate code deployments to Amazon EC2 instances.</p> <p> Additionally, three other new services were revealed that are related to enterprise security and compliance: <a href="http://aws.amazon.com/kms/">AWS Key Management Service</a> (AWS KMS), <a href="http://aws.amazon.com/config/">AWS Config</a>, and <a href="http://aws.amazon.com/servicecatalog/">AWS Service Catalog</a>.</p> <p> <a href="http://aws.amazon.com/rds/aurora/">Amazon RDS for Aurora</a> was also announced during the first keynote. Amazon Aurora is a new, MySQL-compatible, relational database engine built for high performance and availability.</p> <p> The keynote on the second day boasted even more announcements, including the new <a href="https://aws.amazon.com/ecs/">Amazon EC2 Container Service</a>, which is a highly scalable, high performance container management service that supports <a href="https://www.docker.com/">Docker</a> containers.</p> <p> Also, new <a href="https://aws.amazon.com/blogs/aws/new-c4-instances/">compute-optimized (C4) Amazon EC2 Instances</a> were announced, as well as new <a href="https://aws.amazon.com/blogs/aws/larger-faster-ebs-ssd-volumes/">larger and faster Elastic Block Store (EBS) volumes</a> backed with SSDs.</p> <p> <a href="https://aws.amazon.com/lambda/">AWS Lambda</a> was introduced during the second keynote, as well. It is a new compute service that runs your code in response to events and automatically manages the compute resources for you. To learn about AWS Lambda in more detail, you should check out <a href="https://www.youtube.com/watch?v=UFj27laTWQA">their session at re:Invent</a>, which shows how you can implement image thumbnail generation in your applications using AWS Lambda and the new <a href="https://aws.amazon.com/blogs/aws/s3-event-notification/">Amazon S3 Event Notifications</a> feature. They also briefly mention the upcoming <a href="http://aws.amazon.com/blogs/aws/dynamodb-streams-preview/">DynamoDB streams</a> feature in that presentation, which was announced just prior to the conference.</p> <p> The APIs for AWS CodeDeploy, AWS KMS, AWS Config, and AWS Lambda are currently available, and all are supported in the AWS SDK for PHP as of <a href="https://github.com/aws/aws-sdk-php/releases/tag/2.7.5">version 2.7.5</a>.</p> <h2> PHP Presentations</h2> <p> I had the honor of presenting a session about the PHP SDK called <a href="https://www.youtube.com/user/AmazonWebServices/Cloud?x=us-en_reinvent20142_3921_168"><em>Building Apps with the AWS SDK for PHP</em></a>, where I explained how to use many of the new features from <a href="http://blogs.aws.amazon.com/php/post/Tx3RR28K9AAHPD1/Version-3-Preview-of-the-AWS-SDK">Version 3 of the SDK</a> in the context of building an application I called &quot;SelPHPies with ElePHPants&quot;. You should definitely check it out whether you are new to or experienced with the SDK.</p> <p> Here are the links to my presentation as well as two other PHP-specific sessions that you might be interested in.</p> <ul> <li> Building Apps with the AWS SDK for PHP (<a href="http://www.slideshare.net/AmazonWebServices/dev305-building-apps-with-the-aws-sdk-for-php-aws-reinvent-2014-41529323">slides</a>, <a href="https://www.youtube.com/user/AmazonWebServices/Cloud?x=us-en_reinvent20142_3921_168">video</a>)</li> <li> Best Practices for Running WordPress on AWS (<a href="http://www.slideshare.net/AmazonWebServices/web302-best-practices-for-running-wordpress-on-aws-aws-reinvent-2014">slides</a>, <a href="https://www.youtube.com/user/AmazonWebServices/Cloud?x=us-en_reinvent20142_3864_181">video</a>)</li> <li> Running and Scaling Magento on AWS (<a href="https://www.youtube.com/user/AmazonWebServices/Cloud?x=us-en_reinvent20142_3865_181">video</a>)</li> </ul> <p> There were so many other great presentations at re:Invent. The <a href="http://www.slideshare.net/AmazonWebServices/tag/reinvent2014">slides</a>, <a href="https://www.youtube.com/user/AmazonWebServices/Cloud">videos</a>, and <a href="https://itunes.apple.com/us/podcast/aws-re-invent-2014/id941313180">podcasts</a> for all of the presentations are (or will be) posted online.</p> <h2> PHPeople</h2> <p> Announcements and presentations are exciting and informative, but my favorite part about any conference is the people. Re:Invent was no exception.</p> <p> It was great to run into familiar faces from my Twitter stream like <a href="https://twitter.com/juokaz">Juozas Kaziukėnas</a>, <a href="https://twitter.com/ramsey">Ben Ramsey</a>, <a href="https://twitter.com/bdeshong">Brian DeShong</a>, and <a href="https://twitter.com/ziniman">Boaz Ziniman</a>. I also had the pleasure of meeting some new friends from companies that had sent their PHP developers to the conference.</p> <h2> See You Next Year</h2> <p> We hope you take the time to check out some of the presentations from this year’s event, and consider attending next year. Get notified about registration for next year’s event by signing up for the re:Invent mailing list on the <a href="https://reinvent.awsevents.com/">AWS re:Invent website</a>.</p> Version 3 Preview of the AWS SDK https://aws.amazon.com/blogs/developer/version-3-preview-of-the-aws-sdk/ Tue, 14 Oct 2014 20:21:53 +0000 2a31743520a97f287c2b666e24f07623dd4cdb68 We’re excited to introduce you to the preview release of Version 3 of the AWS SDK for PHP! As of today, the preview release of Version 3 (V3) is available on GitHub and via Composer. Two years ago, we released Version 2 (V2) of the SDK. Since then, thousands of developers and companies have adopted […] <p> We’re excited to introduce you to the <strong>preview release of Version 3</strong> of the AWS SDK for PHP! As of today, the preview release of Version 3 (V3) is <a href="https://github.com/aws/aws-sdk-php/releases/tag/3.0.0-beta.1">available on GitHub</a> and via Composer.</p> <p> Two years ago, we released Version 2 (V2) of the SDK. Since then, <em>thousands</em> of developers and companies have adopted it. We are sincerely grateful to all of our users and contributors. We have been constantly collecting your feedback and ideas, and continually watching the evolution of PHP, AWS, and the Guzzle library.</p> <p> Earlier this year, we felt we could make significant improvements to the SDK, but only if we could break a few things. Since receiving a unanimously positive response to our <a href="http://blogs.aws.amazon.com/php/post/TxNB95LUU2J6X7/Guzzle-4-and-the-AWS-SDK">blog post about updating to the latest version of Guzzle</a> a few months ago, we’ve been working hard on V3, and we’re ready to share it with you.</p> <h2> What’s new?</h2> <p> The new version of the SDK provides a number of important benefits to AWS customers. It is smaller and faster, with <strong>improved performance</strong> for both serial and concurrent requests. It has several new features based on its use of the new <a href="http://mtdowling.com/blog/2014/10/13/guzzle-5/">Guzzle 5</a> library (which also includes the new features from <a href="http://mtdowling.com/blog/2014/03/29/guzzle4/">Guzzle 4</a>). The SDK will also, starting from V3, follow the official <a href="http://semver.org">SemVer</a> spec, so you can have complete confidence when setting version constraints in your projects’ <code>composer.json</code> files.</p> <p> Let’s take a quick look at some of the new features.</p> <h3> Asynchronous requests</h3> <p> With V3, you can perform asynchronous operations, which allow you to more easily send requests concurrently. To achieve this, the SDK returns <em>future</em> result objects when you specify the <code>@future</code> parameter, which block only when they are accessed. For managing more robust asynchronous workflows, you can retrieve a <em>promise</em> from the future result, to perform logic once the result becomes available or an exception is thrown.</p> <pre class="brush: php;"> &lt;?php // Upload a file to your bucket in Amazon S3. // Use '@future' to make the operation complete asynchronously. $result = $s3Client-&gt;putObject([ 'Bucket' =&gt; 'your-bucket', 'Key' =&gt; 'docs/file.pdf', 'Body' =&gt; fopen('/path/to/file.pdf', 'r'), '@future' =&gt; true, ]); </pre> <p> After creating a result using the <code>@future</code> attribute, you now have a future result object. You can use the data stored in the future in a blocking (or synchronous) manner by just using the result as normal (i.e., like a PHP array).</p> <pre class="brush: php;"> // Wait until the response has been received before accessing its data. echo $result['ObjectURL']; </pre> <p> If you want to allow your requests to complete asynchronously, then you should use the promise API of the future result object. To retrieve the promise, you must use the <code>then()</code> method of the future result, and provide a callback to be completed when the promise is fulfilled. <a href="https://promisesaplus.com/">Promises</a> allow you to more easily compose pipelines when dealing with asynchronous results. For example, we could use promises to save the Amazon S3 object’s URL to an item in an Amazon DynamoDB table, once the upload is complete.</p> <pre class="brush: php;"> // Note: $result is the result of the preceding example's PutObject operation. $result-&gt;then( function ($s3Result) use ($ddbClient) { $ddbResult = $ddbClient-&gt;putItem([ 'TableName' =&gt; 'your-table', 'Item' =&gt; [ 'topic' =&gt; ['S' =&gt; 'docs'], 'time' =&gt; ['N' =&gt; (string) time()], 'url' =&gt; ['S' =&gt; $s3Result['ObjectURL']], ], '@future' =&gt; true, ]); // Don't break promise chains; return a value. In this case, we are returning // another promise, so the PutItem operation can complete asynchronously too. return $ddbResult-&gt;promise(); } )-&gt;then( function ($result) { echo &quot;SUCCESS!n&quot;; return $result; }, function ($error) { echo &quot;FAILED. &quot; . $error-&gt;getMessage() . &quot;n&quot;; // Forward the rejection by re-throwing it. throw $error; } ); </pre> <p> The SDK uses the <a href="https://github.com/reactphp/promise">React/Promise</a> library to provide the promise functionality, allowing for additional features such as joining and mapping promises.</p> <h3> JMESPath querying of results</h3> <p> The result object also has a new <code>search()</code> method that allows you to query the result data using <a href="http://jmespath.org/">JMESPath</a>, a query language for JSON (or PHP arrays, in our case).</p> <pre class="brush: php;"> &lt;?php $result = $ec2Client-&gt;describeInstances(); print_r($result-&gt;search('Reservations[].Instances[].InstanceId')); </pre> <p> Example output:</p> <pre class="brush: php;"> Array ( [0] =&gt; i-xxxxxxxx [1] =&gt; i-yyyyyyyy [2] =&gt; i-zzzzzzzz ) </pre> <h3> Swappable and custom HTTP adapters</h3> <p> In V3, cURL is no longer required, but is still used by the default HTTP adapter. However, you can use other HTTP adapters, like the one shipped with Guzzle that uses PHP’s HTTP stream wrapper. You can also write custom adapters, which opens up the possibility of creating an adapter that integrates with a non-blocking event loop like <a href="http://reactphp.org/">ReactPHP</a>.</p> <h3> Paginators</h3> <p> <em>Paginators</em> are a new feature in V3, that come as an addition to <em>Iterators</em> from V2. Paginators are similar to Iterators, except that they yield Result objects, instead of items within a result. This is nice, because it handles the tokens/markers for you, getting multiple pages of results, but gives you the flexibility to extract whatever data you want.</p> <pre class="brush: php;"> // List all &quot;directories&quot; and &quot;files&quot; in the bucket. $paginator = $s3-&gt;getPaginator('ListObjects', [ 'Bucket' =&gt; 'my-bucket', 'Delimiter' =&gt; '/' ]); foreach ($paginator as $result) { $jmespathExpr = '[CommonPrefixes[].Prefix, Contents[].Key][]'; foreach ($result-&gt;search($jmespathExpr) as $item) { echo $item . &quot;n&quot;; } } </pre> <p> Example output:</p> <pre class="brush: php;"> Array ( [0] =&gt; dir1/ [1] =&gt; dir2/ [2] =&gt; file1 [3] =&gt; file2 ... ) </pre> <h3> New event system</h3> <p> Version 3 features a new and improved event system. <code>Command</code> objects now have their own event emitter that is decoupled from the HTTP request events. There is also a new request &quot;progress&quot; event that can be used for tracking upload and download progress.</p> <pre class="brush: php;"> use GuzzleHttpEventProgressEvent; $s3-&gt;getHttpClient()-&gt;getEmitter()-&gt;on('progress', function (ProgressEvent $e) { echo 'Uploaded ' . $e-&gt;uploaded . ' of ' . $e-&gt;uploadSize . &quot;n&quot;; }); $s3-&gt;putObject([ 'Bucket' =&gt; $bucket, 'Key' =&gt; 'docs/file.pdf', 'Body' =&gt; fopen('/path/to/file.pdf', 'r'), ]); </pre> <p> Example output:</p> <pre class="brush: php;"> Uploaded 0 of 5299866 Uploaded 16384 of 5299866 Uploaded 32768 of 5299866 ... Uploaded 5275648 of 5299866 Uploaded 5292032 of 5299866 Uploaded 5299866 of 5299866 </pre> <h3> New client options</h3> <p> For V3, we changed some of the options you provide when instantiating a client, but we added a few <em>new</em> options that may help you work with services more easily.</p> <ul> <li> <strong>&quot;debug&quot;</strong> – Set to <code>true</code> to print out debug information as requests are being made. You’ll see how the <em>Command</em> and <em>Request</em> objects are affected during each event, and an adapter-specific wire log of the request.</li> <li> <strong>&quot;retries&quot;</strong> – Set the maximum number of retries the client will perform on failed and throttled requests. The default has always been 3, but now it is easy to configure.</li> </ul> <p> These options can be set when instantiating client.</p> <pre class="brush: php;"> &lt;?php $s3 = (new AwsSdk)-&gt;getS3([ // Exist in Version 2 and 3 'profile' =&gt; 'my-credential-profile', 'region' =&gt; 'us-east-1', 'version' =&gt; 'latest', // New in Version 3 'debug' =&gt; true, 'retries' =&gt; 5, ]); </pre> <h2> What has changed?</h2> <p> To make all of these improvements for V3, we needed to make some backward-incompatible changes. However, the changes from Version 2 to Version 3 are <em>much fewer</em> than the changes from Version 1 to Version 2. In fact, much of the way you use the SDK will remain the same. For example, the following code for writing an item to an Amazon DynamoDB table looks exactly the same in both V2 and V3 of the SDK.</p> <pre class="brush: php;"> $result = $dynamoDbClient-&gt;putItem([ 'TableName' =&gt; 'Contacts', 'Item' =&gt; [ 'FirstName' =&gt; ['S' =&gt; 'Jeremy'], 'LastName' =&gt; ['S' =&gt; 'Lindblom'], 'Birthday' =&gt; ['M' =&gt; [ 'Month' =&gt; ['N' =&gt; '11'], 'Date' =&gt; ['N' =&gt; '24'], ], ], ]); </pre> <p> There are two important changes though that you should be aware of upfront:</p> <ol> <li> V3 requires <strong>PHP 5.5 or higher</strong> and requires the use of <strong>Guzzle 5</strong>.</li> <li> You must now specify the API version (via the &quot;version&quot; client option) when you instantiate a client. This is important, because it allows you to lock-in to the API versions of the services you are using. This helps us and you maintain backward compatibility between future SDK releases, because you will be in charge of API versions you are using. Your code will never be impacted by new service API versions until you update your version setting. If this is not a concern for you, you can default to the latest API version by setting <code>'version'</code> to <code>'latest'</code> (this is essentially the default behavior of V2).</li> </ol> <h2> What next?</h2> <p> We hope you are excited for Version 3 of the SDK!</p> <p> We look forward to your feedback as we continue to work towards a stable release. Please reach out to us in the comments, on <a href="https://github.com/aws/aws-sdk-php/issues">GitHub</a>, or via Twitter (<a href="https://twitter.com/awsforphp">@awsforphp</a>). We plan to publish more blog posts in the near future to explain some of the new features in more detail. We have already published the <a href="http://docs.aws.amazon.com/aws-sdk-php/v3/api">API docs for V3</a>, but we’ll be working on improving all the documentation for V3, including creating detailed migration and user guides. We’ll also be speaking about V3 in our session at <a href="https://reinvent.awsevents.com/">AWS re:Invent</a>.</p> <p> We will continue updating and making regular releases for V2 on the &quot;master&quot; branch of the SDK’s GitHub repository. Our work on V3 will happen on a separate <a href="https://github.com/aws/aws-sdk-php/tree/v3">&quot;v3&quot; branch</a> until we are ready for a stable release.</p> <p> Version 3 can be installed via Composer using version <code>3.0.0-beta.1</code>, or you can <a href="https://github.com/aws/aws-sdk-php/releases/tag/3.0.0-beta.1">download the aws.phar or aws.zip on GitHub</a>.</p> Keeping Up with the Latest Release https://aws.amazon.com/blogs/developer/keeping-up-with-the-latest-release/ Mon, 15 Sep 2014 22:38:17 +0000 39372b7de42120ce8e97e66d2ceac7e8aa49345a In the past, we’ve used various means to announce new releases of the AWS SDK for PHP. We’ve recently evaluated our options to decide which tools work best with our release process, and are easiest for our users to consume. The best way to track releases of the SDK is to use the &quot;Releases&quot; page […] <p>In the past, we’ve used various means to announce new releases of the AWS SDK<br /> for PHP. We’ve recently evaluated our options to decide which tools work best<br /> with our release process, and are easiest for our users to consume.</p> <p>The best way to track releases of the SDK is to use the <a href="https://github.com/aws/aws-sdk-php/releases">&quot;Releases&quot; page of<br /> our GitHub repo</a>. This page show links to all of the releases, and if you<br /> navigate to a specific releases page, you can see the excerpt of the CHANGELOG<br /> for that release, and download the <code>aws.phar</code> and <code>aws.zip</code>. GitHub allows you<br /> to link directly to the <a href="https://github.com/aws/aws-sdk-php/releases/latest">latest release</a> (i.e.,<br /> https://github.com/aws/aws-sdk-php/releases/latest) and also provides a<br /> <a href="https://github.com/aws/aws-sdk-php/releases.atom">Releases atom feed</a> which gets updated each time we tag a release.</p> <p>We also recommend that you follow <a href="https://twitter.com/awsforphp">@awsforphp</a> on Twitter. We use this<br /> account to make announcements about new releases, blog posts, etc., and often<br /> tweet and retweet other things related to AWS and PHP. We also occasionally like<br /> to ask questions, answer questions, and post tips about the AWS SDK for PHP.</p> <p><strong>Note:</strong> If you are currently subscribed to our PEAR channel’s RSS feed, you<br /> should know that we are no longer making updates to the PEAR channel as of 9/15<br /> (see <a href="http://blogs.aws.amazon.com/php/post/TxFFMBZ80DA1OJ/End-of-Life-of-PEAR-Channel">End of Life of PEAR Channel</a> for more details).</p> <p>So, <a href="https://github.com/aws/aws-sdk-php/releases.atom">subscribe to the Releases atom feed</a> and <a href="https://twitter.com/awsforphp">follow us on Twitter</a> to<br /> stay up-to-date with the SDK and make sure you don’t miss out on any new<br /> features or announcements.</p> End of Life of PEAR Channel https://aws.amazon.com/blogs/developer/end-of-life-of-pear-channel/ Mon, 18 Aug 2014 22:55:59 +0000 1d94d6a80756b5c08f40c6039c16ef2cc94db3bb There’s been a noticeable wave of popular PHP projects recently announcing that they will no longer support PEAR as an installation method. Because the AWS SDK for PHP provides a PEAR channel, we’ve been very interested in the discussion in the community on PEAR channel support. PEAR has been one of the many ways to […] <p> There’s been a noticeable wave of popular PHP projects recently announcing that they will no longer support PEAR as an installation method. Because the AWS SDK for PHP provides a <a href="http://pear.amazonwebservices.com/">PEAR channel</a>, we’ve been very interested in the discussion in the community on PEAR channel support.</p> <p> PEAR has been one of the many ways to install the AWS SDK for PHP since 2010. While it’s served us well, better alternatives for installing PHP packages are now available (i.e., <a href="https://getcomposer.org/">Composer</a>) and literally all of the PEAR dependencies of the AWS SDK for PHP are no longer providing updates to their PEAR channels.</p> <h2> Symfony and Pirum</h2> <p> Fabien Potencier recently blogged about the &quot;<a href="http://fabien.potencier.org/article/72/the-rise-of-composer-and-the-fall-of-pear">Rise of Composer and the fall of PEAR</a>&quot;, stating that he would soon no longer update the PEAR channels for the packages he maintains (e.g., <a href="http://symfony.com/blog/end-of-pear-support-for-symfony">Symfony</a>, <a href="http://blog.twig.sensiolabs.org/post/76626577337/pear-packages-wont-be-published-anymore">Twig</a>, <a href="http://blog.swiftmailer.org/post/84816320238/pear-packages-wont-be-published-anymore">Swiftmailer</a>, etc.):</p> <pre> I've been using PEAR as a package manager since my first PHP project back in 2004. I even wrote a popular PEAR channel server, Pirum (http://pirum.sensiolabs.org/). But today, it's time for me to move on and announce my plan about the PEAR channels I'm managing.</pre> <p> One of the projects that we rely on to build the PEAR channel for the AWS SDK for PHP is <a href="http://pirum.sensiolabs.org/">Pirum</a>, and it has made building a PEAR channel slightly less cumbersome. That said, we’ve had to make small modifications to Pirum over the years to suit our needs. With the announcement that Pirum is no longer maintained, we now have much less confidence in relying on it as a tool used to power one of our installation methods.</p> <p> One of the Symfony project’s Fabien published to a PEAR channel was the <a href="http://symfony.com/doc/current/components/event_dispatcher/introduction.html">Symfony EventDispatcher</a>. The AWS SDK for PHP has a PEAR dependency on the EventDispatcher PEAR channel. Because the channel is no longer updated, users of the SDK via PEAR will not receive any bugfix updates to the EventDispatcher.</p> <h2> PHPUnit</h2> <p> PHPUnit, the most popular unit testing framework for PHP applications, recently <a href="https://github.com/sebastianbergmann/phpunit/wiki/End-of-Life-for-PEAR-Installation-Method">stopped updating their PEAR channels</a>:</p> <pre> We are taking the next step in retiring the PEAR installation method with today's release of PHPUnit 3.7.35 and PHPUnit 4.0.17. These two releases are the last versions of PHPUnit released as PEAR packages. Installing them using the PEAR Installer will trigger a deprecation message on every execution of the commandline test runner.</pre> <p> PHPUnit is the testing framework used to test the AWS SDK for PHP.</p> <h2> Guzzle</h2> <p> Guzzle, another dependency of the AWS SDK for PHP’s PEAR channel, is no longer providing updates to their <a href="http://pear.guzzlephp.org/">PEAR channel</a> since the 3.9.0 release.</p> <h2> AWS SDK for PHP PEAR Channel</h2> <p> With all of these contributing factors, we will no longer be providing updates to the AWS SDK for PHP PEAR channel starting on Monday, September 15th, 2014. Our PEAR channel will still be available to download older versions of the SDK, but it will not receive any further updates after this date.</p> <p> If you are currently using the PEAR channel to install the SDK or build downstream packages (e.g., RPMs), please begin to update your installation mechanism to one of the following alternatives:</p> <ol> <li> Composer (the recommended method).</li> <li> Our zip package that contains all of the dependencies and autoloader. Available at <a href="https://github.com/aws/aws-sdk-php/releases/latest">https://github.com/aws/aws-sdk-php/releases/latest</a>.</li> <li> Our phar file that contains all of the dependencies and sets up an autoloader. Available at <a href="https://github.com/aws/aws-sdk-php/releases/latest">https://github.com/aws/aws-sdk-php/releases/latest</a>.</li> </ol> <p> To stay up to date with important fixes and updates, we strongly recommend migrating to one of the installation methods listed above.</p> <p> More instructions on installing the AWS SDK for PHP can be found in the <a href="http://docs.aws.amazon.com/aws-sdk-php/guide/latest/installation.html">user guide</a>.</p> Release: AWS SDK for PHP – Version 2.6.12 https://aws.amazon.com/blogs/developer/release-aws-sdk-for-php-version-2-6-12/ Thu, 17 Jul 2014 22:21:02 +0000 c261f74bfaae9d86f46a714d7c55f3baff86ddc6 We would like to announce the release of version 2.6.12 of the AWS SDK for PHP. This release adds support for new regions to the Kinesis client and new features to the AWS Support and AWS IAM clients. Install the SDK Install via Composer/Packagist (e.g., &quot;aws/aws-sdk-php&quot;: &quot;~2.6.12&quot;) Download the aws.phar Download the aws.zip <p> We would like to announce the <a href="https://github.com/aws/aws-sdk-php/releases/tag/2.6.12">release of version 2.6.12</a> of the <a href="https://github.com/aws/aws-sdk-php">AWS SDK for PHP</a>. This release adds support for new regions to the Kinesis client and new features to the AWS Support and AWS IAM clients.</p> <h2> Install the SDK</h2> <ul> <li> <a href="https://packagist.org/packages/aws/aws-sdk-php">Install via Composer/Packagist</a> (e.g., <code>&quot;aws/aws-sdk-php&quot;: &quot;~2.6.12&quot;</code>)</li> <li> <a href="https://github.com/aws/aws-sdk-php/releases/download/2.6.12/aws.phar">Download the <code>aws.phar</code></a></li> <li> <a href="https://github.com/aws/aws-sdk-php/releases/download/2.6.12/aws.zip">Download the <code>aws.zip</code></a></li> </ul> Release: AWS SDK for PHP – Version 2.6.11 https://aws.amazon.com/blogs/developer/release-aws-sdk-for-php-version-2-6-11/ Fri, 11 Jul 2014 18:41:18 +0000 cf987d74f7a1d6ce60d79390660ed85f4b7a24ee We would like to announce the release of version 2.6.11 of the AWS SDK for PHP. Added support for Amazon Cognito Identity Added support for Amazon Cognito Sync Added support for Amazon CloudWatch Logs Added support for editing existing health checks and associating health checks with tags to the Amazon Route 53 client Added the […] <p> We would like to announce the release of <a href="https://github.com/aws/aws-sdk-php/releases/tag/2.6.11">version 2.6.11</a> of the AWS SDK for PHP.</p> <ul> <li> Added support for Amazon Cognito Identity</li> <li> Added support for Amazon Cognito Sync</li> <li> Added support for Amazon CloudWatch Logs</li> <li> Added support for editing existing health checks and associating health checks with tags to the Amazon Route 53 client</li> <li> Added the ModifySubnetAttribute operation to the Amazon EC2 client</li> </ul> <h2> Install the SDK</h2> <ul> <li> <a href="https://packagist.org/packages/aws/aws-sdk-php">Install via Composer/Packagist</a>&nbsp;(e.g.,&nbsp;<code>&quot;aws/aws-sdk-php&quot;: &quot;~2.6.11&quot;</code>)</li> <li> <a href="https://github.com/aws/aws-sdk-php/releases/download/2.6.11/aws.phar">aws.phar</a></li> <li> <a href="https://github.com/aws/aws-sdk-php/releases/download/2.6.11/aws.zip">aws.zip</a></li> </ul> Release: AWS SDK for PHP – Version 2.6.10 https://aws.amazon.com/blogs/developer/release-aws-sdk-for-php-version-2-6-10/ Wed, 02 Jul 2014 21:23:33 +0000 21ac4fb7af1ce81ee64ebf74de3ecef815e88391 We would like to announce the release of version 2.6.10 of the AWS SDK for PHP. This release adds support for new regions to the AWS CloudTrail and Amazon Kinesis clients. Install the SDK Install via Composer/Packagist (e.g., &quot;aws/aws-sdk-php&quot;: &quot;~2.6.10&quot;) Download the aws.phar Download the aws.zip <p> We would like to announce the <a href="https://github.com/aws/aws-sdk-php/releases/tag/2.6.10">release of version 2.6.10</a> of the <a href="https://github.com/aws/aws-sdk-php">AWS SDK for PHP</a>. This release adds support for new regions to the AWS CloudTrail and Amazon Kinesis clients.</p> <h2> Install the SDK</h2> <ul> <li> <a href="https://packagist.org/packages/aws/aws-sdk-php">Install via Composer/Packagist</a> (e.g., <code>&quot;aws/aws-sdk-php&quot;: &quot;~2.6.10&quot;</code>)</li> <li> <a href="https://github.com/aws/aws-sdk-php/releases/download/2.6.10/aws.phar">Download the <code>aws.phar</code></a></li> <li> <a href="https://github.com/aws/aws-sdk-php/releases/download/2.6.10/aws.zip">Download the <code>aws.zip</code></a></li> </ul> Release: AWS SDK for PHP – Version 2.6.9 https://aws.amazon.com/blogs/developer/release-aws-sdk-for-php-version-2-6-9/ Thu, 26 Jun 2014 21:48:05 +0000 d2a1090082a8a626ee9d49ef8b52714d73993cd2 We would like to announce the release of version 2.6.9 of the AWS SDK for PHP. This release adds support for uploading document batches and submitting search and suggestion requests to an Amazon CloudSearch domain using the new CloudSearch Domain client. It also adds support for configuring delivery notifications to the Amazon SES client, and […] <p> We would like to announce the <a href="https://github.com/aws/aws-sdk-php/releases/tag/2.6.9">release of version 2.6.9</a> of the <a href="https://github.com/aws/aws-sdk-php">AWS SDK for PHP</a>. This release adds support for uploading document batches and submitting search and suggestion requests to an Amazon CloudSearch domain using the new CloudSearch Domain client. It also adds support for configuring delivery notifications to the Amazon SES client, and updates the Amazon CloudFront client to work with the latest API version.</p> <ul> <li> Added support for the <a href="http://docs.aws.amazon.com/aws-sdk-php/guide/latest/service-cloudsearchdomain.html">CloudSearchDomain client</a>, which allows you to search and upload documents to your CloudSearch domains.</li> <li> Added support for delivery notifications to the Amazon SES client.</li> <li> Updated the CloudFront client to support the 2014-05-31 API.</li> <li> Merged PR #316 as a better solution for issue #309.</li> </ul> <h2> Install the SDK</h2> <ul> <li> <a href="https://packagist.org/packages/aws/aws-sdk-php">Install via Composer/Packagist</a> (e.g., <code>&quot;aws/aws-sdk-php&quot;: &quot;~2.6.9&quot;</code>)</li> <li> <a href="https://github.com/aws/aws-sdk-php/releases/download/2.6.9/aws.phar">Download the <code>aws.phar</code></a></li> <li> <a href="https://github.com/aws/aws-sdk-php/releases/download/2.6.9/aws.zip">Download the <code>aws.zip</code></a></li> </ul> Release: AWS SDK for PHP – Version 2.6.8 https://aws.amazon.com/blogs/developer/release-aws-sdk-for-php-version-2-6-8/ Fri, 20 Jun 2014 18:56:01 +0000 528f9ad45f371c072b123e40ece77951040a7639 We would like to announce the release of version 2.6.8 of the AWS SDK for PHP. This release updates the Amazon Elastic Transcoder and Amazon EMR clients to use the latest service descriptions, and fixes a few issues. Added support for closed captions to the Elastic Transcoder client. Added support for IAM roles to the […] <p> We would like to announce the <a href="https://github.com/aws/aws-sdk-php/releases/tag/2.6.8">release of version 2.6.8</a> of the <a href="https://github.com/aws/aws-sdk-php">AWS SDK for PHP</a>. This release updates the Amazon Elastic Transcoder and Amazon EMR clients to use the latest service descriptions, and fixes a few issues.</p> <ul> <li> Added support for closed captions to the Elastic Transcoder client.</li> <li> Added support for IAM roles to the Elastic MapReduce client.</li> <li> Updated the S3 PostObject to ease customization.</li> <li> Fixed an issue in some EC2 waiters by merging PR #306.</li> <li> Fixed an issue with the DynamoDB <code>WriteRequestBatch</code> by merging PR #310.</li> <li> Fixed issue #309, where the <code>url_stat()</code> logic in the S3 Stream Wrapper was affected by a change in the latest versions of PHP. <strong>If you are running version 5.4.29+, 5.5.13+, or 5.6.0+ of PHP, and you are using the S3 Stream Wrapper, you need to update your SDK in order to prevent runtime errors.</strong></li> </ul> <p> We also released version 2.6.7 last week, but forgot to mention it on the blog. Here are the changes from 2.6.7:</p> <ul> <li> Added support for Amazon S3 server-side encryption using customer-provided encryption keys.</li> <li> Updated the Amazon SNS client to support message attributes.</li> <li> Updated the Amazon Redshift client to support new cluster parameters.</li> <li> Updated PHPUnit dev dependency to 4.* to work around a PHP serializing bug.</li> </ul> <h2> Install the SDK</h2> <ul> <li> <a href="https://packagist.org/packages/aws/aws-sdk-php">Install via Composer/Packagist</a> (e.g., <code>&quot;aws/aws-sdk-php&quot;: &quot;~2.6.8&quot;</code>)</li> <li> <a href="https://github.com/aws/aws-sdk-php/releases/download/2.6.8/aws.phar">Download the <code>aws.phar</code></a></li> <li> <a href="https://github.com/aws/aws-sdk-php/releases/download/2.6.8/aws.zip">Download the <code>aws.zip</code></a></li> </ul>