Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Getting Good with the AWS SDK for PHP

Getting Good with the AWS SDK for PHP

Amazon Web Services and the AWS SDK for PHP continue to put more power into the hands of PHP developers to build robust and scalable applications. With version 2 of the SDK, PHP developers now have a more powerful, flexible, and modern library built on top of existing open source software like the Guzzle HTTP framework and the Symfony 2 Event Dispatcher. In this session you will learn how to use the new AWS SDK for PHP, and examine code samples showing how to work with Amazon S3 and Amazon DynamoDB. You will also learn about how you can quickly deploy your application to AWS Elastic Beanstalk and AWS OpsWorks.

Updated 09/2013.

Jeremy Lindblom

May 22, 2013
Tweet

More Decks by Jeremy Lindblom

Other Decks in Technology

Transcript

  1. Hi there! I'm Jeremy! •  PHP So"ware Engineer at! • 

    Co-author of the AWS SDK for PHP! •  Co-organizer of the Seattle PHP User Group! •  @jeremeamia on and | webjeremy.com! •  I like making funny faces!
  2. Amazon Web Services o#ers a complete set of infrastructure and

    application services that enable you to run virtually everything in the cloud.!
  3. Some of these blocks are for! building your infrastructure,! Amazon

    Elastic Compute Cloud! (EC2)! Amazon Relational Database Service! (RDS)! Amazon! Route 53!
  4. Some of these blocks are for! building your application,! Amazon

    Simple Storage Service! (S3)! Amazon Simple Queue Service! (SQS)! Amazon Simple Email Service! (SES)!
  5. And some of these blocks build on each! other to

    create more complete solutions.! AWS CloudFormation! AWS! Elastic Beanstalk! AWS! OpsWorks!
  6. These building blocks enable you to! do virtually anything in

    the cloud, like…! Streaming movies to millions of users around the world,! Allowing millions people to quickly share things online with friends,! Processing, storing, and distributing images from Mars.!
  7. Amazon S3! Amazon SES! Amazon SimpleDB! Amazon SNS! Amazon SQS!

    Amazon SWF! Amazon VPC! Auto Scaling! AWS CloudHSM! AWS Data Pipeline! AWS Elastic Beanstalk! AWS Import/Export! AWS OpsWorks! AWS Marketplace! AWS Storage Gateway! AWS Support! Elastic Load Balancing! Amazon CloudFormation! Amazon CloudFront! Amazon CloudSearch! Amazon CloudWatch! Amazon Direct Connect! Amazon DynamoDB! Amazon EBS! Amazon EC2! Amazon ElastiCache! Amazon Elastic Transcoder! Amazon EMR! Amazon Glacier! Amazon IAM! Amazon Mechanical Turk! Amazon RDS! Amazon Redshi"! Amazon Route53!
  8. Amazon S3! Amazon SES! Amazon SimpleDB! Amazon SNS! Amazon SQS!

    Amazon SWF! Amazon VPC! Auto Scaling! AWS CloudHSM! AWS Data Pipeline! AWS Elastic Beanstalk! AWS Import/Export! AWS OpsWorks! AWS Marketplace! AWS Storage Gateway! AWS Support! Elastic Load Balancing! Amazon CloudFormation! Amazon CloudFront! Amazon CloudSearch! Amazon CloudWatch! Amazon Direct Connect! Amazon DynamoDB! Amazon EBS! Amazon EC2! Amazon ElastiCache! Amazon Elastic Transcoder! Amazon EMR! Amazon Glacier! Amazon IAM! Amazon Mechanical Turk! Amazon RDS! Amazon Redshi"! Amazon Route53! Compute & Networking! Storage & Content Delivery! Databases! Application Services! Deployment & Management!
  9. Amazon S3! Amazon SES! Amazon SimpleDB! Amazon SNS! Amazon SQS!

    Amazon SWF! Amazon VPC! Auto Scaling! AWS CloudHSM! AWS Data Pipeline! AWS Elastic Beanstalk! AWS Import/Export! AWS OpsWorks! AWS Marketplace! AWS Storage Gateway! AWS Support! Elastic Load Balancing! Amazon CloudFormation! Amazon CloudFront! Amazon CloudSearch! Amazon CloudWatch! Amazon Direct Connect! Amazon DynamoDB! Amazon EBS! Amazon EC2! Amazon ElastiCache! Amazon Elastic Transcoder! Amazon EMR! Amazon Glacier! Amazon IAM! Amazon Mechanical Turk! Amazon RDS! Amazon Redshi"! Amazon Route53! 8 services! less than! a year old!
  10. Amazon S3! Amazon SES! Amazon SimpleDB! Amazon SNS! Amazon SQS!

    Amazon SWF! Amazon VPC! Auto Scaling! AWS CloudHSM! AWS Data Pipeline! AWS Elastic Beanstalk! AWS Import/Export! AWS OpsWorks! AWS Marketplace! AWS Storage Gateway! AWS Support! Elastic Load Balancing! Amazon CloudFormation! Amazon CloudFront! Amazon CloudSearch! Amazon CloudWatch! Amazon Direct Connect! Amazon DynamoDB! Amazon EBS! Amazon EC2! Amazon ElastiCache! Amazon Elastic Transcoder! Amazon EMR! Amazon Glacier! Amazon IAM! Amazon Mechanical Turk! Amazon RDS! Amazon Redshi"! Amazon Route53! Fastest Growing AWS Service Ever! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! Amazon Redshi"! !
  11. AWS services each have an API,! so you can control

    your resources! through programs and scripts.!
  12. So let's provision some servers! from PHP by using the

    AWS SDK for PHP! to talk to the Amazon EC2 API! Amazon EC2!
  13. <?php     require  'vendor/autoload.php';   use  Aws\Common\Aws;    

    $ec2  =  Aws::factory('config.php')-­‐>get('ec2');   $result  =  $ec2-­‐>runInstances(array(      'ImageId'            =>  'ami-­‐af45d59f',      'MinCount'          =>  1,      'MaxCount'          =>  3,      'InstanceType'  =>  'm1.small',   ));     $ids  =  $result-­‐>getPath('Instances/*/InstanceId');   $ec2-­‐>waitUntilInstanceRunning(array(      'InstanceIds'  =>  $ids,   ));   echo  'Provisioned  '  .  count($ids)  .  '  servers.';    
  14. AWS SDKs and Tools! PHP • Java • Python •

    .NET! Ruby • Node.js • iOS • Android! SDKs! AWS CLI • Visual Studio Plugin! Eclipse Plugin • PowerShell Tools! Management Console • iOS App! ! Tools! https://github.com/aws! !
  15. AWS SDK for PHP! •  PHP 5.3+, PSR compliant! • 

    Built on top of Guzzle (guzzlephp.org)! •  Persistent connections, parallel requests! •  Easy pagination, "waiters", other helpers! •  Event hooks, plugins, wire logging!
  16. SDK History! •  Tarzan [2006] ( @skyzyx )! •  CloudFusion

    [2007] ( @skyzyx )! •  AWS SDK for PHP [2010]! ( @skyzyx & @jeremeamia )! •  AWS SDK for PHP 2 [Late 2012]! ( @mtdowling & @jeremeamia )!
  17. require  'vendor/autoload.php';     $s3  =  Aws\S3\S3Client::factory(array(      

     'key'        =>  'your_aws_access_key_id',      'secret'  =>  'your_aws_secret_key',   ));     $body  =  fopen('/path/to/file',  'r');   $result  =  $s3-­‐>putObject(array(      'Bucket'  =>  'my-­‐cool-­‐photos',      'Key'        =>  'photo.jpg',      'Body'      =>  $body,      'ACL'        =>  'public-­‐read',   ));  
  18. Concepts in the SDK! •  Client Factories & Service Builder!

    •  Commands! •  Modeled Results! •  Iterators! •  Waiters! •  Events & Plugins!
  19. use  Aws\Ec2\Ec2Client;     $client  =  Ec2Client::factory(array(      

     'key'        =>  'your-­‐aws-­‐access-­‐key-­‐id',      'secret'  =>  'your-­‐aws-­‐secret-­‐key',      'region'  =>  'us-­‐west-­‐2',   ));   Client Factory!
  20. use  Aws\Common\Aws;     $aws  =  Aws::factory(array(      

     'key'        =>  'your-­‐aws-­‐access-­‐key-­‐id',      'secret'  =>  'your-­‐aws-­‐secret-­‐key',      'region'  =>  'us-­‐west-­‐2',   ));     $client1  =  $aws-­‐>get('ec2');   $client2  =  $aws-­‐>get('ec2');   var_dump($client1  ===  $client2);   Service Builder!
  21. Commands! •  Encapsulates an operation to AWS! •  Contains Request

    and Response objects! •  Allows you set and get parameters! •  Returns modeled results when executed!
  22. Commands - Shorthand! $result  =  $s3-­‐>listObjects(array(      'Bucket'  =>

     'my-­‐bucket-­‐name'   ));     echo  $result['Contents'][0]['Key'];  
  23. $command  =  $s3-­‐>getCommand('ListObjects');   $command-­‐>set('Bucket',  'my-­‐bucket-­‐name');   $command['Bucket']  =  'my-­‐bucket-­‐name';

        $result  =  $command-­‐>getResult();   echo  $result['Contents'][0]['Key'];     $request  =  $command-­‐>getRequest();   $response  =  $command-­‐>getResponse();   echo  $response-­‐>getStatusCode();   echo  $response-­‐>getHeader('Content-­‐Length');     The Command Object!
  24. $c1  =  $s3-­‐>getCommand('PutObject',  array(      'Bucket'  =>  'my-­‐bucket-­‐name',  

       'Key'        =>  'my-­‐first-­‐key',      'Body'      =>  fopen('path/to/file1',  'r')   ));   $c2  =  $s3-­‐>getCommand('PutObject',  array(      'Bucket'  =>  'my-­‐bucket-­‐name',      'Key'        =>  'my-­‐second-­‐key',      'Body'      =>  fopen('path/to/file2',  'r')   ));     $s3-­‐>execute(array($c1,  $c2));   Parallel Commands!
  25. Modeled Results! •  Array-like object! •  Follows schema from service

    description! •  Convenience methods like getPath()   $result  =  $s3-­‐>listBuckets();     $result['Buckets'][0]['Name'];   $result-­‐>get('Buckets');   $result-­‐>getPath('Buckets/0/Name');   print_r($result-­‐>toArray());  
  26. Waiters! •  Poll resources until available! •  Handle asynchronous and

    eventually consistent operations more easily! $s3-­‐>createBucket(array(      'Bucket'  =>  'my-­‐bucket'   ));   $s3-­‐>waitUntilBucketExists(array(      'Bucket'  =>  'my-­‐bucket'   ));  
  27. Iterators! •  Iterate through entire result sets! •  No handling

    of markers or tokens! •  Uses SPL iterators! $list  =  $s3-­‐>getListObjectsIterator([      'Bucket'  =>  'my-­‐bucket'   ]);   foreach  ($list  as  $object)  {      echo  $object['Key']  .  "\n";   }  
  28. SDK 1.x – Before Iterators! $dynamo_db  =  new  AmazonDynamoDB();  

    $start_key  =  null;   $people  =  array();       do  {      $params  =  array(          'TableName'  =>  'people',      );          if  ($start_key)  {        $params['ExclusiveStartKey']  =  array(            'HashKeyElement'  =>  array(                'S'  =>  $start_key            )        );        $start_key  =  null;    }      $response  =  $dynamo_db-­‐>scan($params);    if  ($response-­‐>isOK())  {        foreach   ($response-­‐>body-­‐>Items  as  $item)  {            echo  (string)  $item-­‐>name-­‐>S;        }                  if  ($response-­‐>body-­‐>LastEvaluatedKey)  {            $start_key  =  (string)  $response-­‐>body   -­‐>LastEvaluatedKey-­‐>HashKeyElement-­‐>S;        }      }  else  {                  throw  new  DynamoDB_Exception('…');    } }  while  ($start_key);
  29. SDK 1.x – Before Iterators! $dynamo_db  =  new  AmazonDynamoDB();  

    $start_key  =  null;   $people  =  array();       do  {      $params  =  array(          'TableName'  =>  'people',      );          if  ($start_key)  {        $params['ExclusiveStartKey']  =  array(            'HashKeyElement'  =>  array(                'S'  =>  $start_key            )        );        $start_key  =  null;    }      $response  =  $dynamo_db-­‐>scan($params);    if  ($response-­‐>isOK())  {        foreach   ($response-­‐>body-­‐>Items  as  $item)  {            echo  (string)  $item-­‐>name-­‐>S;        }                  if  ($response-­‐>body-­‐>LastEvaluatedKey)  {            $start_key  =  (string)  $response-­‐>body   -­‐>LastEvaluatedKey-­‐>HashKeyElement-­‐>S;        }      }  else  {                  throw  new  DynamoDB_Exception('…');    } }  while  ($start_key);
  30. $db  =  $aws-­‐>get('DynamoDb');     $scan  =  $db-­‐>getScanIterator(array(    

     'TableName'              =>  'People',      'AttributesToGet'  =>  array('Id',  'Name')   ));     foreach  ($scan  as  $person)  {      echo  $item['Name']['S'];   }     Example: Scan Iterator!
  31. Events & Event Listeners! •  Event slots in various parts

    of SDK! (Clients, Requests, Waiters, Batches, etc.)! •  Inject logic without extending classes! •  Every client has an instance of the Symfony2 EventDispatcher! $s3-­‐>getEventDispatcher()        -­‐>addListener('<event>',  <fn>);  
  32. Plugins! •  Implemented as event subscribers! •  Request signing implemented

    this way! •  Many built-in plugins from Guzzle including easy wire logging! use  Guzzle\Plugin\Log\LogPlugin;   $s3-­‐>addSubscriber(          LogPlugin::getDebugPlugin()   );  
  33. AWS Services for our App! $ $AWS Elastic Beanstalk! $

    $Amazon S3! $ $( Simple Storage Service )! $ $Amazon DynamoDB! $ $AWS IAM! $ $( Identity and Access Management )!
  34. AWS Elastic Beanstalk! •  Easy to get started! •  PHP

    5.3 or PHP 5.4! •  Does load balancing and auto scaling! •  Deploy via Git, upload (console), or S3 (API)! •  Installs Composer dependencies for you! •  Customize via API/console, ebextensions con%g, and custom hook scripts!
  35. require  __DIR__  .  '/vendor/autoload.php';     use  Aws\Common\Enum\Region;   use

     Aws\Silex\AwsServiceProvider;   use  Silex\Application;     $app  =  new  Application;   $app-­‐>register(new  AwsServiceProvider(),  array(      'aws.config'  =>  array(              'key'        =>  'AKEXAMPLE8FOO29JBAR8Q',              'secret'  =>  'Sf0Example24Foo0J4Bar3XBaz34',            'region'  =>  Region::US_EAST_1,      )   ));   Let's Use Silex, Twig, & AWS!
  36. SDK Third-party Integrations! •  Silex service provider! •  Laravel 4

    service provider! •  Zend Framework 2 module! •  Gaufrette adapter!
  37. require  __DIR__  .  '/vendor/autoload.php';     use  Aws\Common\Enum\Region;   use

     Aws\Silex\AwsServiceProvider;   use  Silex\Application;     $app  =  new  Application;   $app-­‐>register(new  AwsServiceProvider(),  array(      'aws.config'  =>  array(              'key'        =>  'AKEXAMPLE8FOO29JBAR8Q',              'secret'  =>  'Sf0Example24Foo0J4Bar3XBaz34',            'region'  =>  Region::US_EAST_1,      )   ));   Credential Problem!
  38. IAM Roles & Instance Pro%les! •  An IAM Role lets

    you give other AWS users and services access to your AWS resources.! •  An IAM Instance Pro%le is an association of an IAM Role to an Amazon EC2 Instance.! •  The AWS SDK for PHP will automatically use Instance Pro%le Credentials if available.! •  You can con%gure your Elastic Beanstalk environment with an Instance Pro%le.!
  39. require  __DIR__  .  '/vendor/autoload.php';     use  Aws\Common\Enum\Region;   use

     Aws\Silex\AwsServiceProvider;   use  Silex\Application;     $app  =  new  Application;   $app-­‐>register(new  AwsServiceProvider(),  array(      'aws.config'  =>  array(              'region'  =>  Region::US_EAST_1,      )   ));   Instance Pro%le Credentials! Do not provide any credentials, and the SDK will automatically use your Instance Profile Credentials.
  40. $app-­‐>get('/photos',  function  ()  use  ($app)  {      $db  =

     $app['aws']-­‐>get('dynamodb');      $faces  =  $db-­‐>getScanIterator([              'TableName'  =>  'funny-­‐face'      ]);        return  $app['twig']-­‐>render('index.twig',[              'faces'  =>  $faces      ]);   });   Index Controller!
  41. $app-­‐>get('/photos',  function  ()  use  ($app)  {      $db  =

     $app['aws']-­‐>get('dynamodb');      $faces  =  $db-­‐>getScanIterator([              'TableName'  =>  'funny-­‐face'      ]);        return  $app['twig']-­‐>render('index.twig',[              'faces'  =>  $faces      ]);   });   Index Controller!
  42. The Shape of an Item! {        "src":

     {              "S":  "https://funny-­‐face.s3.amazonaws.com/2rlDm.jpg"        },        "caption":  {              "S":  "You  had  one  job!"        }  ,        "size":  {              "N":  "205993423"        }   },  
  43. use  Aws\DynamoDb\Iterator\ItemIterator  as  Items;   $app-­‐>get('/photos',  function  ()  use  ($app)

     {      $db  =  $app['aws']-­‐>get('dynamodb');      $faces  =  new  Items($db-­‐>getScanIterator([              'TableName'  =>  'funny-­‐face'      ]);        return  $app['twig']-­‐>render('index.twig',[              'faces'  =>  $faces      ]);   });   Index Controller Revisited!
  44. $app-­‐>match('/photos/add',  function()  use($app)  {      //  ...  ($file  is

     a  Symfony\Component\HttpFoundation\File\UploadedFile)      $s3  =  $app['aws']-­‐>get('s3');      $url  =  $s3-­‐>putObject([              'Bucket'          =>  'funny-­‐face',              'Key'                =>  $file-­‐>getFileName(),              'SourceFile'  =>  $file-­‐>getPathname(),              'ACL'                =>  CannedAcl::PUBLIC_READ,      ])-­‐>get('ObjectURL');      //  ...   });   Add Controller - Upload!
  45. $app-­‐>match('/photos/add',  function($request)  use($app)  {      //  ...    

     $db  =  $app['aws']-­‐>get('dynamodb');      $msg  =  $request-­‐>request-­‐>get('caption',  'None');      $db-­‐>putItem([              'TableName'  =>  'funny-­‐face',              'Item'            =>  [                      'src'          =>  ['S'  =>  $url],                      'caption'  =>  ['S'  =>  $msg]              ],      ]);      //  ...   });   Add Controller - Save!
  46. AWS OpsWorks! •  DevOps solution for apps! •  Organized w/

    stacks & layers! •  Deploy from a GitHub repo! •  Customize with Chef recipes! •  Nice management console!
  47. $s3  =  $aws-­‐>get('S3');   $uploader  =  UploadBuilder::newInstance()      -­‐>setClient($s3)

         -­‐>setSource('./videos/video42.mov')      -­‐>setBucket('app-­‐media')      -­‐>setKey('videos/video42.mov')      -­‐>setConcurrency(3)      -­‐>build();   Multipart Uploader!
  48. $s3-­‐>upload(      'app-­‐media',            

           //  Bucket      'videos/video42.mov',  //  Key      fopen('/tmp/vidz/video42.mov',  'r')   );   Simple Upload! Automatically uses single or multipart upload for you depending on %le size.!
  49. $s3-­‐>registerStreamWrapper();     $path  =  's3://jcl-­‐files/logs/04.log';   if  ($file  =

     fopen($path,  'r'))  {      while  (!feof($file))  {          echo  fgets($file);      }      fclose($file)   }   Amazon S3 Stream Wrapper!
  50. $s3-­‐>registerStreamWrapper();     $finder  =  new  Finder();   $finder-­‐>files()  

       -­‐>in('s3://jcl-­‐files/family-­‐videos')      -­‐>size('<  50M')      -­‐>date('since  1  year  ago');     foreach  ($finder  as  $file)  {      echo  $file-­‐>getFilename()  .  "\n";   }   Stream Wrapper + Symfony Finder!
  51. Need Help with the SDK?! •  Homepage http://aws.amazon.com/sdkforphp/! •  Github

    https://github.com/aws/aws-sdk-php! •  User Guide http://docs.aws.amazon.com/aws-sdk-php-2/guide/latest/! •  API Docs http://docs.aws.amazon.com/aws-sdk-php-2/latest/! •  Blog http://blogs.aws.amazon.com/php! •  Forum https://forums.aws.amazon.com/forum.jspa?forumID=80!