(DEV305) Building Apps with the AWS SDK for PHP | AWS re:Invent 2014

Post on 02-Jul-2015

894 views 1 download

description

For both new and experienced users of the AWS SDK for PHP, we highlight features of the SDK as we work through building a simple, scalable PHP application. Attendees will learn about core features of the SDK including service clients, iterators, and waiters. We will also introduce new features in the upcoming Version 3 of the SDK, including asynchronous requests, paginators, and the new JMESPath result querying syntax.

Transcript of (DEV305) Building Apps with the AWS SDK for PHP | AWS re:Invent 2014

November 12, 2014 | Las Vegas, NV

Jeremy Lindblom (@jeremeamia), AWS Developer Resources

@awsforphp

1. Introduce the SDK (including Version 3)

2. Build an app with the SDK

3. Demonstrate advanced SDK features

$ec2 = ::factory

'region' => 'us-east-1'

'version' => '2014-06-15'

$ec2->runInstances

'ImageId' => 'ami-6a6dcc02'

'MinCount' =>

'MaxCount' =>

'InstanceType' => 'm1.small'

(semver.org)

(cont.)

$ec2 = ::factory

'region' => 'us-east-1'

$ec2->runInstances

'ImageId' => 'ami-6a6dcc02'

'MinCount' =>

'MaxCount' =>

'InstanceType' => 'm1.small'

$ec2 = ::factory

'region' => 'us-east-1'

$ec2->runInstances

'ImageId' => 'ami-6a6dcc02'

'MinCount' =>

'MaxCount' =>

'InstanceType' => 'm1.small'

'version' => '2014-06-15'

• Async requests with Future Result

objects and a Promise API

• Support for custom HTTP adapters

– cURL no longer required (still the default)

– Possible to implement with non-blocking event loops

• Result "Paginators" for iterating paginated data

• JMESPath querying of result data

• "debug" client option for easy debugging

PHP PHP

#nofilter

#selphpie

#instagood

PHP PHP

(Storage of selPHPies)

(Storage of URLs/captions)PHP

PHP

"require": {

"aws/aws-sdk-php": "~3.0@dev",

"silex/silex": "~1.2",

"twig/twig": "~1.16",

}

getcomposer.org

• Instance profile credentials

• Credentials file

• Environment variables

• Hard coding

• Instance profile credentials

• Credentials file

• Environment variables

• Client configuration

• Instance profile credentials

• Credentials file

• Environment variables

• Client configuration

FYI: Also supported by the

AWS CLI and other SDKs.

• Instance profile credentials

• Credentials file

• Environment variables

• Client configuration

• Instance profile credentials

• Credentials file

• Environment variables

• Client Configuration (BEWARE)

'credentials' =>

'key' => $yourAccessKeyId

'secret' => $yourSecretAccessKey

php bin/setup.php

S3 bucket

DynamoDB table

Amazon S3Amazon

DynamoDB

$s3->createBucket 'Bucket' => $bucket

$s3->waitUntil 'BucketExists' 'Bucket' => $bucket

$dynamoDb->createTable(['TableName' => $table ...

$dynamoDb->waitUntil 'TableExists'

'TableName' => $table

echo "Done.\n"

$result = $dynamoDb->createTable([

'TableName' => $table,

'@future' => true,

]);

// Do other things...

// Blocks once dereferenced.

$result['TableDescription']['TableStatus'];

$waiter = $dynamoDb->getWaiter(

'TableExists', [...]

);

$waiter->wait();

// THIS IS THE SAME AS:

$dynamoDb->waitUntil 'TableExists' ...

$result = $client->operation([...]);

$result->then(

$onFulfilled,

$onRejected,

$onProgress,

);

// See the React/Promise library

$dynamoDb->createTable([

'TableName' => $table,

'@future' => true,

])->then(function ($result) use ($dynamoDb, $table) {

return $dynamoDb->getWaiter('TableExists', [

'TableName' => $table,

])->promise();

})->then(function ($result) {

echo "Done.\n";

});

$dynamoDb->createTable([…])

->then(...)

->then(...);

$s3->createBucket([…])

->then(...)

->then(...);

$app = new

$app 'aws' = function

return new

'region' => 'us-east-1'

'version' => 'latest'

// ROUTES AND OTHER APPLICATION LOGIC

$app->run

$app->get '/' function ...

$dynamoDb = $app 'aws' ->getDynamoDb

$result = $dynamoDb->query

'TableName' => 'selphpies'

'Limit' =>

// ...

$items = $result 'Items'

$results = $dynamoDb->getPaginator 'Query'

'TableName' => 'selphpies'

// ...

$items = $results->search 'Items[]'

$results = $s3->getPaginator 'ListObjects' ...

$files = $results->search 'Contents[].Key'

# With Paginators

$results = $s3->getPaginator 'ListObjects'

'Bucket' => 'my-bucket'

$keys = $results->search 'Contents[].Key'

foreach $keys as $key

echo $object 'Key' . "\n"

# Without Paginators

$marker =

do

$args = 'Bucket' => 'my-bucket'

if $marker

$args 'Marker' = $marker

$result = $s3->listObjects $args

$objects = array $result 'Contents'

foreach $objects as $object

echo $object 'Key' . "\n"

$marker $result->search

'NextMarker || Contents[-1].Key'

while $result 'IsTruncated'

http://jmespath.org/

$result->search '<JMESPath Expression>'

> 'Contents[].Key'

> '[CommonPrefixes[].Prefix, Contents[].Key][]'

> 'NextMarker || Contents[-1].Key'

$app->get '/upload' function ...

POST

$app->post '/upload' function ...

try {

$caption = $request->request->get('selphpieCaption', '...');

$file = $request->files->get('selphpieImage');

if (!$file instanceof UploadedFile || $file->getError()) {

throw new \RuntimeException('...');

}

#1. UPLOAD THE IMAGE TO S3

#2. SAVE THE IMAGE DATA TO DYNAMODB$app['session']->getFlashBag()->add('alerts', 'success');

return $app->redirect('/');

} catch (\Exception $e) {

$app['session']->getFlashBag()->add('alerts', 'danger');

return $app->redirect('/upload');

}

$s3 = $app['aws']->getS3();

$result = $s3->putObject([

'Bucket' => 'selphpies',

'Key' => $file->getClientOriginalName(),

'Body' => fopen($file->getFileName(), 'r'),

'ACL' => 'public-read',

]);

// Automatically switches to multipart uploads

// if the file is larger than default threshold.

$result = $s3->upload(

'selphpies',

$file->getClientOriginalName(),

fopen($file->getPathname(), 'r'),

'public-read'

);

$dynamoDb->putItem([

'TableName' => 'selphpies',

'Item' => [

// ...

'src' => ['S' => $result['ObjectURL']],

'caption' => ['S' => $caption],

],

]);

PHP

such php

so cloud

wow

very selfie

much app

#phpdoge

PHP

Really

PHP

PHP

PHP

PHP

Step 1

Step 2Step 3 Step 4

Step 1

$results = $dynamoDb->getPaginator 'Scan'

'TableName' => $oldTable

'KeyConditions' =>

Step 2

$records = new $dynamoDb

'table' => $newTable

// $records->put($selphpie);

$records->flush

Step 3

$commands =

$commands = $s3->getCommand 'CopyObject' ...

$commands = $s3->getCommand 'CopyObject' ...

$commands = $s3->getCommand 'CopyObject' ...

// ...

$s3->executeAll $commands

$getCopyCommands = function $results use ...

foreach $results->search 'Items[]' as $selphpie

$command = $s3->getCommand 'CopyObject'

'Bucket' => $newBucket

'Key' => $key

'SourceFile' => "{$oldBucket}/{$key}"

// ... (Attach event listener in Step 4) ...

yield $command

$s3->executeAll $getCopyCommands $results

Step 4

$emitter = $command->getEmitter

$emitter->on 'process' function $event use ...

if $result = $event->getResult

$selphpie 'url' 'S' = $result 'ObjectURL'

// Add new record to WriteRequestBatch

$records->put $selphpie

else

// Log/handle error...

PHP

Step 1

Step 2Step 3 Step 4

PHP

$results = $dynamoDb->getPaginator('Scan', [

'TableName' => $oldBucket,

'KeyConditions' => [

'app' => [

'AttributeValueList' => [['S' => $oldAppKey]],

'ComparisonOperator' => 'EQ',

],

],

]);

$records = new WriteRequestBatch($dynamoDb, [

'table' => $newTable

]);

$getCopyCommands = function ($results) use (

$s3, $records, $oldBucket, $newBucket, $newAppKey

) {

foreach ($results->search('Items[]') as $selphpie) {

$key = Url::fromString($selphpie['url']['S'])->getPath();

$command = $s3->getCommand('CopyObject', [

'Bucket' => $newBucket,

'Key' => $key,

'SourceFile' => "{$oldBucket}/{$key}",

]);

$emitter = $command->getEmitter();

$emitter->on('process', function ($event) use (

$selphpie, $records, $newAppKey

) {

if ($result = $event->getResult()) {

$selphpie['url']['S'] = $result['ObjectURL'];

$selphpie['app']['S'] = $newAppKey;

// Add new record to WriteRequestBatch

$records->put($selphpie);

} else {

// Log/handle error...

}

});

yield $command;

}

};

$s3->executeAll($getCopyCommands($results));

$records->flush();

@awsforphp

github.com/aws/aws-sdk-php/releases

blogs.aws.amazon.com/php

github.com/aws/aws-sdk-php

forums.aws.amazon.com

http://bit.ly/awsevals

@awsforphp

Come find us at the AWS booths

if you have questions.

Your Homework: