Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

67
© 2013 Amazon.com, Inc. and its affiliates. All rights reserved. May not be copied, modified, or distributed in whole or in part without the express consent of Amazon.com, Inc. Mastering the AWS SDK for PHP Michael Dowling & Jeremy Lindblom, AWS Developer Resources November 15, 2013

description

The AWS SDK for PHP allows PHP developers to interact with AWS services in a fluid and familiar way. Learn how to use convenience features, like iterators and waiters, as well as high-level abstractions, such as the Amazon Simple Storage Service (Amazon S3) stream wrapper. We also demonstrate the powerful capabilities inherited from the underlying Guzzle library.

Transcript of Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Page 1: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

© 2013 Amazon.com, Inc. and its affiliates. All rights reserved. May not be copied, modified, or distributed in whole or in part without the express consent of Amazon.com, Inc.

Mastering the AWS SDK for PHP

Michael Dowling & Jeremy Lindblom, AWS Developer Resources

November 15, 2013

Page 2: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

PART 1

PART 2

Using the AWS SDK for PHP

by working with

Amazon S3

High-level features

for common use cases

with the AWS SDK for PHP

Page 3: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

AWS SDK for PHP

https://github.com/aws/aws-sdk-php

@awsforphp

Follow Us!

Page 4: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

AWS SDK for PHP

• Suite of HTTP clients for AWS services

• Built on top of Guzzle (guzzlephp.org) – Persistent connections, parallel requests

– Event hooks, plugins, wire logging

• Helpful functionality – Easy pagination

– "waiters"

– Automatic retries

– etc.

Page 5: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

AWS SDK for PHP – Installing

• Composer / Packagist

• Phar

• Zip

• PEAR

• Yum (Amazon Linux)

Page 6: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

AWS SDK for PHP – Installing via Composer

{

"require": {

"aws/aws-sdk-php": "~2.4"

}

}

> composer.phar install

In your composer.json:

From your terminal:

http://getcomposer.org

Page 7: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Using the AWS SDK for PHP

PART 1

Page 8: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Using the AWS SDK for PHP

CreateBucket

PutObject

ListObjects

Amazon S3 operations

Page 9: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Amazon Simple Storage Service (Amazon S3)

Scalable storage in the cloud

http://my-stuff.s3.amazonaws.com/photos/kittens.jpg

Bucket Name Object Key

Page 10: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Using the AWS SDK for PHP

CreateBucket

PutObject

ListObjects

Page 11: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Creating a Bucket – Complete Example

<?php

require 'vendor/autoload.php';

use Aws\Common\Aws;

use Aws\S3\Exception\S3Exception;

$aws = Aws::factory('config.php');

$s3 = $aws->get('s3');

try {

$result = $s3->createBucket([

'Bucket' => 'bucket-name',

]);

$s3->waitUntilBucketExists([

'Bucket' => 'bucket-name',

]);

} catch (S3Exception $e) {

echo $e->getMessage();

}

Page 12: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Two Ways to Instantiate a Service Client

1. Client factory method

2. Service builder (Aws\Common\Aws)

Page 13: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Instantiate a Client via its Factory Method

use Aws\S3\S3Client;

$s3 = S3Client::factory([

'key' => '{your-aws-access-key-id}',

'secret' => '{your-aws-secret-key}',

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

]);

Page 14: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Instantiate a Client via the Service Builder

<?php

require 'vendor/autoload.php';

use Aws\Common\Aws;

$aws = Aws::factory('/path/to/config.php');

$s3 = $aws->get('s3');

$s3again = $aws->get('s3');

var_dump($s3 === $s3again); #> bool(true)

Page 15: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Providing Credentials

• Options array ['key' => '?', 'secret' => '?']

• Configuration file

• Environment credentials – AWS_ACCESS_KEY_ID

– AWS_SECRET_KEY

• IAM Instance Profile credentials

See http://blogs.aws.amazon.com/php

(Providing credentials to the AWS SDK for PHP)

Page 16: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Executing a Command

try {

$result = $s3->createBucket([

'Bucket' => $bucket,

]);

} catch (Aws\S3\Exception\S3Exception $e) {

echo $e->getMessage();

}

Page 17: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Executing a Command – API Docs

Page 18: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Handling a Response – Modeled Responses

$result = $s3->listBuckets();

$result['Buckets']; // Implements ArrayAccess

print_r($result->toArray());

echo $result;

$result->getPath('Buckets/0/Name');

$result->getPath('Buckets/*/Name');

Page 19: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Handling a Response – API Docs

Page 20: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Wire Logging – Debug Easily

<?php

require 'vendor/autoload.php';

use Aws\Common\Aws;

use Aws\S3\Exception\S3Exception;

use Guzzle\Plugin\Log\LogPlugin;

$aws = Aws::factory('config.php');

$s3 = $aws->get('s3');

$log = LogPlugin::getDebugPlugin();

$s3->addSubscriber($log);

try {

$result = $s3->createBucket([

'Bucket' => 'bucket-name',

]);

$s3->waitUntilBucketExists([

'Bucket' => 'bucket-name',

]);

} catch (S3Exception $e) {

echo $e->getMessage();

}

use Guzzle\Plugin\Log\LogPlugin;

$log = LogPlugin::getDebugPlugin();

$s3->addSubscriber($log);

Page 21: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Wire Logging – Output

# Request:

PUT / HTTP/1.1

Host: this-is-my-test-wonderful-bucket.s3.amazonaws.com

User-Agent: aws-sdk-php2/2.4.6 Guzzle/3.7.3 curl/7.25.0 PHP/5.3.27

Date: Wed, 25 Sep 2013 23:03:13 +0000

Authorization: AWS AKIAEXAMPLEEXAMPLE:Xn2lJPREXAMPLEQkPmY0IAUng=

Content-Length: 0

# Response:

HTTP/1.1 200 OK

x-amz-id-2: eNUZEXAMPLEM4U7c/4WPIlshkfVUEXAMPLEUkyKirVgjEXAMPLEsfwZ3Mx

x-amz-request-id: C91E6E8CD19680F7

Date: Wed, 25 Sep 2013 23:03:15 GMT

Location: /this-is-my-test-wonderful-bucket

Page 22: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Plugins

• Plugin architecture from Guzzle

• Uses the Symfony Event Dispatcher

• Many plugins included with Guzzle

(Log, Backoff, History, Mock, HTTP Cache, etc.)

Page 23: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Wait for it…

<?php

require 'vendor/autoload.php';

use Aws\Common\Aws;

use Aws\S3\Exception\S3Exception;

$aws = Aws::factory('config.php');

$s3 = $aws->get('s3');

try {

$result = $s3->createBucket([

'Bucket' => 'bucket-name',

]);

$s3->waitUntilBucketExists([

'Bucket' => 'bucket-name',

]);

} catch (S3Exception $e) {

echo $e->getMessage();

}

Page 24: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Waiters

• Poll resources until available

• Handle asynchronous and eventually consistent

operations more easily

$result = $s3->createBucket([ 'Bucket' => $bucket ]);

$s3->waitUntilBucketExists([ 'Bucket' => $bucket ]);

Page 25: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Using the AWS SDK for PHP

CreateBucket

PutObject

ListObjects

Page 26: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Uploading an Object to Amazon S3

$result = $s3->putObject([

'Bucket' => 'my-cool-photos',

'Key' => 'photos/photo01.jpg',

'Body' => fopen('/path/to/photo01.jpg', 'r'),

'ACL' => 'public-read',

]);

$url = $result->get('ObjectURL');

Page 27: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Command Syntax – Short vs. Long Form

// Short form

$result = $s3->putObject([

// ...

]);

// Long form

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

// ...

]);

$result = $command->getResult();

Page 28: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Executing Commands in Parallel

$command1 = $s3->getCommand('PutObject', [

'Bucket' => 'my-bucket-name',

'Key' => 'my-first-key',

'Body' => fopen('path/to/file1.ext', 'r')

]);

$command2 = $s3->getCommand('PutObject', [

'Bucket' => 'my-bucket-name',

'Key' => 'my-second-key',

'Body' => fopen('path/to/file2.ext', 'r')

]);

$s3->execute([$command1, $command2]);

Page 29: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Using the AWS SDK for PHP

CreateBucket

PutObject

ListObjects

Page 30: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Listing Objects in Your Bucket

$result = $s3->listObjects([

'Bucket' => 'my-bucket-name',

]);

$nextResult = $s3->listObjects([

'Bucket' => 'my-bucket-name',

'Marker' => 'photos/photo-1000.jpg',

]);

Page 31: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Iterators – Enumerate Your Data Easily

• Iterate through entire result sets

• No handling of markers or tokens

• Lazy loads results

• Compatible with SPL iterators

Page 32: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Iterators – Enumerating Your Data Easily

$objects = $s3->getListObjectsIterator([

'Bucket' => 'my-bucket-name',

]);

foreach ($objects as $object) {

echo $object['Key'] . "\n";

}

Page 33: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

SDK 1.x – A Time Before Iterators

$sk = null;

$people = array();

do {

$params = array('TableName'=>'people');

if ($sk) {

$params['ExclusiveStartKey'] = array(

'HashKeyElement' => array(

'S' => $sk

)

);

$sk= null;

}

$r = $dynamo_db->scan($params);

if ($r->isOK()) {

foreach ($r->body->Items as $item) {

echo (string) $item->name->S;

}

if ($lk = $r->body->LastEvaluatedKey) {

$sk = (string) $lk->HashKeyElement->S;

}

} else {

throw new DynamoDB_Exception('...');

}

}

while ($sk);

Page 34: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

SDK 1.x – A Time Before Iterators

$sk = null;

$people = array();

do {

$params = array('TableName'=>'people');

if ($sk) {

$params['ExclusiveStartKey'] = array(

'HashKeyElement' => array(

'S' => $sk

)

);

$sk= null;

}

$r = $dynamo_db->scan($params);

if ($r->isOK()) {

foreach ($r->body->Items as $item) {

echo (string) $item->name->S;

}

if ($lk = $r->body->LastEvaluatedKey) {

$sk = (string) $lk->HashKeyElement->S;

}

} else {

throw new DynamoDB_Exception('...');

}

}

while ($sk);

Page 35: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

SDK 2.x – The Era of Iterators

$scan = $db->getScanIterator([

'TableName' => 'People',

'AttributesToGet' => ['Id', 'Name']

]);

foreach ($scan as $person) {

echo $item['Name']['S'];

}

Page 36: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Advanced Iterator Usage – Example

$objects = $s3->getListObjectsIterator([

'Bucket' => 'my-bucket-name',

]);

$objects = new LimitIterator($objects, 0, 5);

foreach ($objects as $object) {

echo $object['Key'] . "\n";

}

Page 37: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Using the AWS SDK for PHP

CreateBucket

PutObject

ListObjects

Page 38: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

High-level Abstractions in the AWS SDK for PHP

PART 2

Page 39: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

"I want to use Amazon S3 like a local filesystem."

Amazon S3 Stream Wrapper

Page 40: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

PHP Stream Wrappers

• Provide a

consistent I/O

interface for

various protocols – fopen(), fread(),

file_get_contents(), mkdir(), etc…

– file://, http://, ftp://,

php://, …

Page 41: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

PHP Stream Wrapper Protocols

echo file_get_contents('/path/to/file');

Is equivalent to…

echo file_get_contents('file:///path/to/file');

file:// is the protocol

Page 42: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

PHP Stream Wrapper Protocols

echo file_get_contents('http://www.amazon.com');

http:// is the protocol

Page 43: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Amazon S3 Stream Wrapper

// First, register the wrapper

$s3 = Aws\S3\S3Client::factory();

$s3->registerStreamWrapper();

echo file_get_contents('s3://bucket_name/key');

file_put_contents('s3://bucket_name/key', 'hi!');

s3:// bucket_name /key

Page 44: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Pseudo-directory

• Amazon S3 knows about buckets and keys

• There aren't real subdirectories

• Pseudo-directories can be created using a key

prefix

Bucket: foo

Key: baz/bar/bam

URL: http://foo.s3.amazonaws.com/baz/bar/bam

Page 45: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Reading bytes off of a stream

$fp = fopen('s3://bucket_name/key', 'r');

while (!feof($fp)) {

echo fread($fp, 1024);

}

fclose($fp);

Instead of reading all bytes up front and then using them

Page 46: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Using Stream Filters

$in = fopen('s3://bucket_name/key.zip', 'r');

$out = fopen('/path/to/file', 'w');

stream_filter_append($out, 'zlib.inflate');

stream_copy_to_stream($in, $out);

fclose($in);

fclose($out);

Filters are used for: Conversion, Compression, Encryption, etc.

Page 47: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Listing Objects and Buckets

$dir = "s3://bucket_name/";

if (is_dir($dir) && ($dh = opendir($dir))) {

while (($file = readdir($dh)) !== false) {

echo "Name: {$file}\n";

}

closedir($dh);

}

Page 48: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Listing Objects and Buckets

$dir = 's3://bucket_name';

$iterator = new RecursiveIteratorIterator(

new RecursiveDirectoryIterator($dir),

RecursiveIteratorIterator::CHILD_FIRST

);

foreach ($iterator as $file) {

echo $file->getType() . ': ' . $file . "\n";

}

The more intuitive recursive iterator iterator iterator iterator …

Page 49: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Listing Objects and Buckets

file: s3://bucket/aws_logo.png

file: s3://bucket/background.gif

file: s3://bucket/channel.xml

file: s3://bucket/data.txt

file: s3://bucket/destruct

dir: s3://bucket/dirupload

file: s3://bucket/dirupload/aws-autoloader.php

file: s3://bucket/dirupload/aws.zip

file: s3://bucket/dirupload/guzzle/guzzle/.gitignore

file: s3://bucket/dirupload/guzzle/guzzle/.travis.yml

file: s3://bucket/dirupload/guzzle/guzzle/CHANGELOG.md

file: s3://bucket/dirupload/guzzle/guzzle/LICENSE

Page 50: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

PHP Stream Wrappers: Summary

• Access Amazon S3 like a local filesystem

• Read bytes off of a stream on demand

• Use familiar methods like file_get_contents

• Access to PHP's stream filters

Page 51: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

"I need to upload a local directory to

an Amazon S3 bucket"

For static blogs, websites, etc.

Page 52: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013
Page 53: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013
Page 54: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013
Page 55: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013
Page 56: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

.

├── images

│ ├── dotted-border.png

│ ├── email.png

│ ├── noise.png

│ ├── rss.png

│ └── search.png

├── index.html

Local filesystem

.

├── images

│ ├── dotted-border.png

│ ├── email.png

│ ├── noise.png

│ ├── rss.png

│ └── search.png

├── index.html

Amazon S3 Bucket

Page 57: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

uploadDirectory()

$client->uploadDirectory('/local/directory', 'bucket');

1. Recursively iterates over all local files

2. Checks if the file does not exist or if it has changed

3. Uploads matching files (single or multipart)

public function uploadDirectory(

$directory,

$bucket,

$keyPrefix = null,

array $options = array()

)

Page 58: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Key Prefix?

https://bucket.s3.amazonaws.com/blogs/index.html

$client->uploadDirectory(

'/local/dir',

'bucket',

'blogs/' // Key prefix

);

Page 59: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

uploadDirectory() Options

$client->uploadDirectory('/local/dir', 'bucket', '', [

'params' => ['ACL' => 'public-read'],

'concurrency' => 20,

'debug' => true

]);

Debug output:

Uploading /local/dir/images/email.png -> images/email.png (8 bytes)

Uploading /local/dir/images/noise.png -> images/noise.png (12 bytes)

Uploading /local/dir/images/rss.png -> images/rss.png (100 bytes)

Uploading /local/dir/images/search.png -> images/search.png (200 bytes)

Uploading /local/dir/index.html -> index.html (1024 bytes)

Page 60: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

"I need to download an Amazon S3 bucket to

my local filesystem"

Page 61: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

downloadBucket()

$client->downloadBucket ('/local/directory', 'bucket');

Works exactly like uploadDirectory()

public function downloadBucket(

$directory,

$bucket,

$keyPrefix = null,

array $options = array()

)

Page 62: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Sync Amazon S3 -> Amazon S3

$client->uploadDirectory(

's3://bucket_src',

'bucket_dest'

);

Upload the contents of one Amazon S3 bucket to another using

uploadDirectory().

Page 63: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

"I need to use the SDK with my framework."

Page 64: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Third-party Integrations

• Laravel 4 Service Provider

• Zend Framework 2 Module

• Silex Service Provider

https://github.com/aws

If you'd like to help us or contribute to another

framework integration, please come talk to us.

Page 65: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Mastering the AWS SDK for PHP

Learned how to use the AWS SDK for PHP by

working with some basic Amazon S3 operations.

Learned how to speed up some common

development use cases by using some of the

SDK's high-level abstractions.

Page 66: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

What you will do next

• Star ★ the AWS SDK for PHP GitHub repo https://github.com/aws/aws-sdk-php

• composer install the SDK into your project https://packagist.org/packages/aws/aws-sdk-php

• Subscribe to the AWS PHP Development Blog http://blogs.aws.amazon.com/php

• Build cool PHP apps on the AWS cloud!

Page 67: Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013

Please give us your feedback on this

presentation

As a thank you, we will select prize

winners daily for completed surveys!

TLS306

Mastering the AWS SDK for PHP

Follow us: @awsforphp