はじめに
この記事は、駆け出しエンジニアのための 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
を追加します。
extension=json.so
こちらについては以下のカスタムランタイムのGithubのREADMEにて解説があります。
https://github.com/stackery/php-lambda-layer
プログラムの作成
データ登録処理
<?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";
}
データ取得処理
<?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 用のデプロイファイル
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