#SDKのインストール
AWS SDK for PHPをLaravelに取り込みましょう。
プロジェクトルートで下記コマンドを実行します。
$ composer require aws/aws-sdk-php
これでvendor配下にSDKがインストールされます。
DynamoDBに接続する
AWS SDK for PHPでつなぐにはこのようにします。
下記の例ではクレデンシャルを含めていますが、この方法は推奨されていないので注意してください
ハードコードされた認証情報の使用
use Aws\Sdk;
$awsSdk = new Sdk([
'credentials' => [
'key' => アクセスキー,
'secret' => シークレットキー,
],
'endpoint' => 'エンドポイント',
'region' => 'リージョン',
'version' => 'バージョン'
]);
$dynamo = $awsSdk->createDynamoDb();
以上。
Laravelらしくしよう
と、まあこれじゃあちょっとLaravelらしくないよね、ってことでDIしてみます。new禁止。
envに登録
dotEnv便利ですよね。
AWS_DYNAMO_KEY=アクセスキー
AWS_DYNAMO_SECRET=シークレットキー
AWS_DYNAMO_ENDPOINT=エンドポイント
AWS_DYNAMO_REGION=リージョン
AWS_DYNAMO_VERION=バージョン
ServiceProviderを記述
LaravelでDIといえばServiceProviderですよね。
<?php
declare(strict_types=1);
namespace App\Providers;
use Aws\DynamoDb\DynamoDbClient;
use Aws\Sdk;
use Illuminate\Support\ServiceProvider;
class DynamoServiceProvider extends ServiceProvider
{
/**
* Dynamo AWS-SDK接続
*/
public function register()
{
$this->app->singleton(DynamoDbClient::class, function () {
$awsSdk = new Sdk([
'credentials' => [
'key' => env('AWS_DYNAMO_KEY'),
'secret' => env('AWS_DYNAMO_SECRET'),
],
'endpoint' => env('AWS_DYNAMO_ENDPOINT'),
'region' => env('AWS_DYNAMO_REGION'),
'version' => env('AWS_DYNAMO_VERSION')
]);
return $awsSdk->createDynamoDb();
});
}
}
Laravelなら config/app.phpのproviders に登録。
'providers' => [
App\Providers\DynamoServiceProvider::class,
Lumenならbootstrap/app.phpに登録します。
$app->register(App\Providers\DynamoServiceProvider::class);
コンストラクタインジェクション
ここまでできたら、お好きな場所でインジェクションできます。Facadeにしてもいいかもですね。
/**
* @var DynamoDbClient
*/
private $client;
/**
* constructor.
* @param DynamoDbClient $client
*/
public function __construct(DynamoDbClient $client)
{
$this->client = $client;
}
Eloquentっぽくしよう
Dynamoにアクセスするのに毎回
$this->client->putItem($paramertes);
とかって書くのめんどいですよね。
普段使い慣れているEloquentやQueryBuilderっぽく、find()とかsave()とかdestory()とか使いたいです。
じゃあ、EloqentModelに変わる基底クラスを作っちゃいましょう。
DynamoModelを作る
たとえばこんな感じでしょうか。
<?php
declare(strict_types=1);
namespace App\Models\Dynamo;
use Aws\DynamoDb\DynamoDbClient;
use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;
use Aws\Result;
use Illuminate\Support\Str;
/**
* Class DynamoModel
* @package App\Models\Dynamo
*/
class DynamoModel
{
/**
* @var string
*/
protected $primaryKey = 'id';
/**
* @var string|null
*/
protected $table = null;
/**
* @var DynamoDbClient
*/
private $client;
/**
* @var Marshaler
*/
private $marshaler;
/**
* DynamoModel constructor.
* @param DynamoDbClient $client
* @param Marshaler $marshaler
*/
public function __construct(DynamoDbClient $client, Marshaler $marshaler)
{
$this->client = $client;
$this->marshaler = $marshaler;
}
/**
* @return string
*/
public function getTable(): string
{
$tableName = $this->table ?? Str::snake(Str::pluralStudly(class_basename($this)));
return env('APP_ENV', 'local') . '_' . $tableName;
}
/**
* DynamoにINSERT
* @param array $attributes
* @return Result
*/
public function save(array $attributes): Result
{
$marshalItem = $this->marshaler->marshalItem($attributes);
$dynamoParameters = [
'TableName' => $this->getTable(),
'Item' => $marshalItem
];
try {
return $this->client->putItem($dynamoParameters);
} catch (DynamoDbException $exception) {
throw $exception;
}
}
/**
* Dynamoからレコード削除
* @param array $ids
*/
public function destroy(array $ids): void
{
foreach ($ids as $id) {
$deleteParameter = [$this->primaryKey => $id];
$marshalItem = $this->marshaler->marshalItem($deleteParameter);
$dynamoParameters = [
'TableName' => $this->getTable(),
'Key' => $marshalItem
];
try {
$this->client->deleteItem($dynamoParameters);
} catch (DynamoDbException $exception) {
throw $exception;
}
}
}
/**
* Dynamoから1件レコードを取得
* @param int $id
* @return array|null
*/
public function find(int $id): ?array
{
$idParameter = [$this->primaryKey => $id];
$marshalItem = $this->marshaler->marshalItem($idParameter);
$dynamoParameters = [
'TableName' => $this->getTable(),
'Key' => $marshalItem
];
try {
$awsResult = $this->client->getItem($dynamoParameters)->get('Item');
if (is_null($awsResult)) {
return null;
}
return $this->marshaler->unmarshalItem($awsResult);
} catch (DynamoDbException $exception) {
throw $exception;
}
}
}
あとはこれを継承したModelをつかえば、EloquentみたいにDynamoにアクセスできるようになります。
必要に応じで、findOrFail()でもupdateOrCreate()でもはやしていけばいいのかなーと思います。