autoprotect-group / php-dynamodb-odm
PHP 对象文档映射器,用于 AWS DynamoDB
Requires
- php: ^8.1
- ext-bcmath: *
- adbario/php-dot-notation: ^3.1
- aws/aws-sdk-php: ^3.218
- doctrine/annotations: ^1.13
- moneyphp/money: ^4.0
Requires (Dev)
- behat/behat: ^3.10
- defuse/php-encryption: ^2.3
- henzeb/enumhancer: ^1.11
- koriym/attributes: ^1.0
- phpspec/phpspec: ^7.2
- phpspec/prophecy: ^1.15
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.6
This package is auto-updated.
Last update: 2024-08-27 14:52:48 UTC
README
这是一个库,也是一个对象文档映射器,可以更方便地与 AWS DynamoDB 一起使用。
用法
配置 ODM
设置原生客户端
$dynamoDbClient = new DynamoDbClient(array_merge( [ 'region' => 'eu-west-2', 'version' => 'latest', ] ));
设置主要操作库客户端
$client = new DynamodbOperationsClient($dynamoDbClient);
设置序列化器。原生 AWS 序列化器可能被采用
$marshaler = new Marshaler();
设置查询构建器
$queryBuilder = new QueryBuilder($marshaler, new ExpressionFactory($marshaler));
设置注解读取器和注解管理器
// annotation reader $annotationReader = new AnnotationReader(); // annotation manager $annotationManager = new AnnotationManager($annotationReader);
模型的填充器
$newModelHydrator = new Hydrator(NewModel::class, $annotationManager); $sortKeyModelHydrator = new Hydrator(SortKeyModel::class, $annotationManager);
用于将记录插入数据库的序列化器
// serializer for $serializer = new Serializer($annotationManager);
完整的示例在这里。
模型
模型字段类型
库使用模型进行操作。每个模型可能有各种支持的字段类型。以下是与 PHP 和 DynamoDb 类型相关联的类型列表
BooleanType
:DynamoDb 和 PHP 中的布尔值CollectionType
:DynamoDb 中的列表,在 PHP 中是特定模型项的数组列表DateType
:DynamoDb 中的字符串,PHP 中的 DateTimeEnumType
:DynamoDb 中的字符串,PHP 中的枚举FloatType
:DynamoDb 中的数字,PHP 中的浮点数HashMapType
:DynamoDb 中的映射,在 PHP 中是特定模型项的关联数组IntegerType
:DynamoDb 中的数字,PHP 中的整型ModelType
:DynamoDb 中的映射,PHP 中的模型实例Money
:DynamoDb 中的映射,PHP 中的特殊 MoneyObject。作为Money 值的概念NumberType
:DynamoDb 中的数字。一个抽象类型,不是特别方便。偶尔可能会用到ScalarCollectionType
:DynamoDb 中的映射。在 PHP 中是任何 DynamoDb 兼容类型的关联数组,但不包括CollectionType
、HashMapType
或ModelType
StringType
:DynamoDb 和 PHP 中的字符串
以下是模型示例
class ExampleDemoModel extends Model { protected const TABLE_NAME = 'test-table'; // Primary means that this is a partition key for the DynamoDb table #[StringType, Primary] protected string $id; #[StringType] protected string $name; #[FloatType] protected float $price; #[Money] protected Money $priceNet; #[FloatType] protected float $percent; #[IntegerType] protected int $itemsAmount; #[DateType] protected DateTime $createdAt; #[BooleanType] protected bool $isDeleted; #[BooleanType] protected bool $isPhoneNumber; #[ModelType([ModelType::MODEL_CLASS_NAME => RelatedModel::class])] protected RelatedModel $buyer; #[CollectionType([CollectionType::MODEL_CLASS_NAME => RelatedModel::class])] protected array $buyers; #[ModelType([Asset::MODEL_CLASS_NAME => Asset::class])] protected Asset $asset; #[HashMapType([HashMapType::MODEL_CLASS_NAME => RelatedModel::class])] protected array $buyersMap; // getter and setters should be here }
完整的模型示例在这里:model.php
枚举示例
枚举也受到支持。以下是具有枚举字段的模型示例
class ModelWithEnumeration extends Model { #[Primary, StringType] protected string $id; #[EnumType] protected OrderStatus $orderStatus; // union types #[EnumType] protected OrderStatus|ApplicationStatus $unionStatus; // union types with null #[EnumType] protected OrderStatus|ApplicationStatus|null $unionNullableStatus; // isStrict means the value will be null in case wrong value comes from the DB #[EnumType(isStrict: false)] protected ?OrderStatus $orderStatusAdditional = null; #[EnumType] protected CustomerType $customerType; }
字段加密
某些类型的自定义加密受到支持。如果有某些字段需要加密。
首先我们需要创建一个自定义加密器
MyEncryptor implements EncryptorInterface { protected const ENCRYPTION_KEY = 'def000008053addc0f94b14c0e480a10631a0a970b3565e5a7a2aeaeeb51a39e2d139a8977bc02be0195f0036a29aefff9df6d2ddb81432d14b4dce82b83b3a95c6d0205'; public function decrypt(string|array $encryptedData, array $options = []): string|array { // any decryption way may be implemented if (is_array($encryptedData)) { // ...specific property decryption operations... return $encryptedData; } return Crypto::decrypt( $encryptedData, Key::loadFromAsciiSafeString(static::ENCRYPTION_KEY) ); } }
然后应该将解密器传递给填充器
$newModelHydrator = new Hydrator( EncryptionDemoModel::class, $annotationManager, new MyEncryptor(), );
模型可能如下所示
class EncryptionDemoModel extends Model { #[Key\Primary, Types\StringType] protected string $id; // ability to encrypt a specific property in a scalar associative array #[Types\ScalarCollectionType, Encrypted(["encryptedProperty" => "secretProperty"])] protected array $encryptedArray; #[Types\StringType, Encrypted] protected string $encryptedName; }
为您的模型设置存储库
操作记录的最佳方式是创建一个存储库。已经内置了一个
$newModelDynamoDbRepository = new DynamoDBRepository( NewModel::class, $client, $queryBuilder, $newModelHydrator, $annotationManager, $marshaler, $serializer );
默认存储库中包含内置操作。
按分区 ID 获取模型
仅通过分区键
$foundModel = $newModelDynamoDbRepository->get($id);
通过分区键和排序键
$foundModel = $newModelDynamoDbRepository->get($id, $sortKey);
非一致读取
$foundModel = $newModelDynamoDbRepository->get($id, $sortKey, false);
获取一个项目
$foundModel = $newModelDynamoDbRepository->getOneById($id, $sortKey, false);
插入模型
$newModelDynamoDbRepository->save($model);
删除项
$newModelDynamoDbRepository->delete($model);
文档存储库
有时我们需要获取的不是整个模型,而只是它的一部分。为此,存在所谓的 DocumentRepository
。可以使用原生 DynamoDb 投影表达式技术获取文档的一部分。
设置 DocumentRepository
$documentRepository = new DocumentRepository( NewModelNested::class, $client, $this->queryBuilder, $this->newModelHydrator, $annotationManager, $marshaler, $serializer );
通过投影表达式获取模型
$projectionExpression = "property.subPropertyModel"; $model = $documentRepository->getDocument() ->setConsistentRead(true) ->withAttrPath($projectionExpression) ->withPrKey($keyValue) ->execute() ;
通过投影表达式获取特定的标量属性
$projectionExpression = "property.subPropertyModel.name"; $name = $this->documentRepository->getDocumentProperty() ->setConsistentRead(true) ->withAttrPath($projection) ->withPrKey($keyValue) ->execute() ;
获取/创建/更新/删除操作
文档存储库支持特定的属性获取/创建/更新/删除操作
createDocument()
updateDocument()
removeDocument()
getDocumentCollection()
updateDocumentCollection()
createDocumentCollection()
查询构建器
另一个强大的功能是查询构建器。这增加了通过DynamoDB支持的特定标准检索项的灵活性。
这是使用原始查询和结果与DynamoDB交互的一种方式。
获取查询构建器
检索项
$getItemQuery = $queryBuilder ->getItem(self::DB_TABLE) ->itemKey([$itemKey => $keyValue]) ->getQuery(); $item = $this->dynamoDbClient ->getItem($getItemQuery)->get('Item');
更新查询构建器
能够更新特定属性。
$attributesForUpdate = [ "numberProp" => 2, "stringProp" => "updated string value", "hashMapProp.map-id-1.type" => "updated map-type-1", "hashMapProp.map-id-1.mapProp" => "updated mapProp", "listProp" => [ "updated listProp 1", "updated listProp 2" ] ]; $getItemQuery = $queryBuilder ->updateItem(self::DB_TABLE) ->itemKey([$itemKey => $keyValue]) ->attributes($attributesForUpdate) ->getQuery(); $dynamoDbClient->updateItem($getItemQuery);
本地开发环境安装
- 为了构建开发镜像,请运行以下命令:
docker-compose build
- 然后运行以下命令安装依赖项:
docker-compose run --no-deps dynamodb-odm composer install
运行测试
单元测试
此包使用phpspec运行单元测试。
使用以下方式运行它们:
docker-compose run --no-deps dynamodb-odm vendor/bin/phpspec run
可以在.env.local
文件中使用环境变量来调试库。为此,只需将文件.env.local.sample复制到.env.local,并根据您的操作系统设置变量。
然后使用以下命令运行测试:
docker-compose --env-file ./.env.local run --no-deps dynamodb-odm vendor/bin/phpspec run
功能测试
此包使用behat运行功能测试。
然后直接运行测试
docker-compose run dynamodb-odm vendor/bin/behat -c behat.yml --stop-on-failure
语法检查测试
您需要通过运行以下命令来检查代码风格是否正确:
docker-compose run --no-deps dynamodb-odm vendor/bin/phpcs --standard=/application/phpcs.xml