AWS Lambda でPHP動かして DynamoDBを操作する

AWS Lambda でPHP動かして DynamoDBを操作する:


はじめに

この記事は、駆け出しエンジニアのための Advent Calendar 2018の15日目の記事です


re:Invent2018

先日ラスベガスで開催された、AWS re:Invent2018にて、

AWS Lambdaに、Custom Runtimeという機能が追加され、

Lambdaのサポート外の言語もLambda上で実行可能となりました。

今回は、PHPをLambda上で動かすために、STACKERYより提供されているこちらのPHPの Custom Runtimeを使用し、

Lambda上のPHPからDynamodbを操作するためにAWSが提供しているAWS SDK for PHPを使います。


環境

  • AWS CLI

    デプロイ用
  • AWS SAM CLI

    デプロイ用
  • Composer
    AWS SDK for PHPをインストールするために使用します。
インストールはリンクのURLを参考にしてください


開発準備

  • 処理対象となる、DynamoDBを作成する

  • 以下IAMポリシーがあるロールを作成する



    • AmazonDynamoDBFullAccess
    • AWSLambdaDynamoDBExecutionRole
  • デプロイ用にファイルを上げるS3バケットを作成する
  • 以下の構成でディレクトリを作成
|-- src 
|   `-- php 
`-- template.yml //AWS SAM CLI のデプロイ時に必要な構成ファイル 
  • AWS SDK for PHPのインストール
$ php composer require aws/aws-sdk-php 
  • php.iniの編集
今回使用しているPHPのCustom Runtime上ではデフォルトで、json.soの機能が使えません。
AWS SDK for PHPでは内部でjson.soを使用しているため有効化する必要があります。

PHPのCustom Runtime上で、json.soを有効化するために、php.iniファイルを作成し、

以下のようにextension を追加します。

php.ini
extension=json.so 
こちらについては以下のカスタムランタイムのGithubのREADMEにて解説があります。
https://github.com/stackery/php-lambda-layer


プログラムの作成

データ登録処理

post.php
<?php 
require 'vendor/autoload.php'; 
 
use Aws\Sdk; 
use Aws\DynamoDb\Marshaler; 
use Aws\DynamoDb\Exception\DynamoDbException; 
 
$tableName = 'php_test'; //対象のテーブル名 
$name = $_GET["name"]; //GETでリクエストされたデータ(name)を取得 
 
$sdk = new Sdk([ 
    'region'   => 'ap-northeast-1', //使用するregion情報 
    'version'  => 'latest' 
]); 
 
$dynamodb = $sdk->createDynamoDb(); 
$marshaler = new Marshaler(); 
 
$uid = uniqid(); //登録用にuuidを作成 
 
$item = $marshaler->marshalJson('{ 
        "id": "' . $uid . '", 
        "name": "'. $name .'" 
    } 
'); 
 
$params = [ 
    'TableName' => $tableName, 
    'Item' => $item 
]; 
 
try { 
    $result = $dynamodb->putItem($params); 
    echo "Added item success id:". $uid; 
} catch (DynamoDbException $e) { 
    echo "Unable to add item:\n"; 
    echo $e->getMessage() . "\n"; 
} 
データ取得処理

getphp
<?php 
require 'vendor/autoload.php'; 
 
use Aws\Sdk; 
use Aws\DynamoDb\Marshaler; 
use Aws\DynamoDb\Exception\DynamoDbException; 
 
$tableName = 'php_test'; //対象のテーブル名 
$id = $_GET["id"]; //GETでリクエストされたデータ(id)を取得 
 
$sdk = new Sdk([ 
    'region'   => 'ap-northeast-1', //使用するregion情報 
    'version'  => 'latest' 
]); 
 
$dynamodb = $sdk->createDynamoDb(); 
$marshaler = new Marshaler(); 
 
$key = $marshaler->marshalJson('{ 
        "id": "' . $id . '" 
    } 
'); 
 
$params = [ 
    'TableName' => $tableName, 
    'Key' => $key 
]; 
 
try { 
    $result = $dynamodb->getItem($params); 
    print_r($result["Item"]); 
} catch (DynamoDbException $e) { 
    echo "Unable to get item:\n"; 
    echo $e->getMessage() . "\n"; 
} 
 
最終的なディレクト構成 以下ようになります

|-- src 
|   `-- php 
|       |-- vendor //AWS SDK for PHP 
|       |-- composer.json //Composer file 
|       |-- composer.lock //Composer file 
|       |-- get.php //データ取得用処理 
|       |-- php.ini // php.ini 
|       `-- post.php //データ登録用処理 
`-- template.yml 
AWS SAM CLI 用のデプロイファイル

template.yml
AWSTemplateFormatVersion: 2010-09-09 
Description: My PHP Application 
Transform: AWS::Serverless-2016-10-31 
Resources: 
  phppost: 
    Type: AWS::Serverless::Function 
    Properties: 
      FunctionName: !Sub test-phppost 
      Description: PHP Post 
      Role: [作成したロール情報] 
      CodeUri: src/php 
      Runtime: provided 
      Handler: post.php 
      MemorySize: 3008 
      Timeout: 30 
      Tracing: Active 
      Layers: 
        - !Sub arn:aws:lambda:[region]:887080169480:layer:php71:5 
      Events: 
        api: 
          Type: Api 
          Properties: 
            Path: /post 
            Method: ANY 
 
  phpget: 
    Type: AWS::Serverless::Function 
    Properties: 
      FunctionName: !Sub test-phpget 
      Description: PHP Get 
      Role: [作成したロール情報] 
      CodeUri: src/php 
      Runtime: provided 
      Handler: get.php 
      MemorySize: 3008 
      Timeout: 30 
      Tracing: Active 
      Layers: 
        - !Sub arn:aws:lambda:[region]:887080169480:layer:php71:5 
      Events: 
        api: 
          Type: Api 
          Properties: 
            Path: /get 
            Method: ANY 


デプロイ

パッケージしてS3バケットへアップロード

$ sam package --template-file template.yml --output-template-file serverless-output.yaml --s3-bucket [作成したS3バケット] 
デプロイ

sam deploy --template-file serverless-output.yaml --stack-name custom-runtime-php71  --capabilities CAPABILITY_IAM 


動作検証

API Gatewayも同時に作成されているので、自動的に作成されたURLを確認し動作検証する

  • 登録処理
     
    登録する内容をURLパラメータ name をリクエストする
https://xxxxxxx.execute-api.[resion].amazonaws.com/Prod/post?name=tanaka 


レスポンスとして、発行されたIDが返却される

Added item success id:5c14940af36b0 
  • データ取得処理
発行されたIDを取得用のキーとするためURLパラメータ id をリクエストする

https://xxxxxx.execute-api.[resion].amazonaws.com/Prod/get?id=5c14940af36b0 


以下のようにDynamoDBから取得したデータが表示される

Array ( [id] => Array ( [S] => 5c1524cec4aa7 ) [name] => Array ( [S] => tanaka ) ) 
DynamoDBを確認するとリクエストしたデータが登録されているはずです


参考

https://dev.classmethod.jp/cloud/aws/php-vpc-lambda-alb-rds/
https://dev.classmethod.jp/cloud/aws/lambda-custom-runtime-php-extension
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/GettingStarted.PHP.03.html

コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)