bf-dsf / php-dynamodb-odm
PHP ODM for dynamodb
Requires
- php: ^7.1|^8.0
- bf-dsf/aws-wrappers: ^2.14
- doctrine/annotations: ~1.13
- symfony/console: ^5.4
- symfony/finder: ^5.4
Requires (Dev)
- phpunit/phpunit: ^9.5
- dev-master
- v0.8.4
- v0.8.3
- v0.8.2
- v0.8.1
- v0.8.0
- v0.7.22
- v0.7.21
- v0.7.20
- v0.7.19
- v0.7.18
- v0.7.17
- v0.7.16
- v0.7.15
- v0.7.14
- v0.7.13
- v0.7.12
- v0.7.11
- v0.7.10
- v0.7.9
- v0.7.8
- v0.7.7
- v0.7.6
- v0.7.5
- v0.7.4
- v0.7.3
- v0.7.2
- v0.7.1
- v0.7.0
- v0.6.1
- v0.6.0
- v0.5.3
- v0.5.2
- v0.5.1
- v0.5.0
- v0.4.25
- v0.4.24
- v0.4.22
- v0.4.21
- v0.4.20
- v0.4.19
- v0.4.18
- v0.4.17
- v0.4.16
- v0.4.15
- v0.4.14
- v0.4.13
- v0.4.12
- v0.4.11
- v0.4.10
- v0.4.9
- v0.4.8
- v0.4.7
- v0.4.6
- v0.4.5
- v0.4.4
- v0.4.3
- v0.4.2
- v0.4.1
- v0.4.0
- v0.3.4
- v0.3.3
- v0.3.2
- v0.3.1
- v0.3.0
- v0.2.8
- v0.2.7
- v0.2.6
- v0.2.5
- v0.2.4
- v0.2.2
- v0.2.1
- v0.2.0
- v0.1.3
- v0.1.2
- v0.1.1
- v0.1.0
- dev-odm_optimalization
This package is auto-updated.
Last update: 2024-09-27 17:38:41 UTC
README
bf-dsf/php-dynamodb-odm 是一个 ODM(对象数据映射)库,用于简化 AWS 强大的键值数据库 DynamoDb 的使用。
注意:本文档假设您已了解 DynamoDb 是什么以及 DynamoDb 与传统关系数据库管理系统(例如 MySQL)之间的区别。本文档中讨论的一些术语和概念是针对 DynamoDb 的特定内容,不会在本文档中解释。要学习 DynamoDb,请参阅官方开发者指南
安装与配置
要获取 bf-dsf/php-dynamodb-odm,您可以通过 composer
直接 require 它
$ composer require bf-dsf/php-dynamodb-odm
类加载
DynamoDb ODM 的自动加载由 composer
负责处理。您只需要将 composer 的自动加载文件包含到您的项目中
<?php require_once "vendor/autoload.php";
获取 ItemManager
一旦您准备好了类加载,您就可以获取一个 ItemManager 实例。ItemManager 类是访问库提供的 ODM 功能的主要访问点。
<?php use BF\Mlib\ODM\Dynamodb\ItemManager; $awsConfig = [ "profile" => "oasis-minhao", "region" => "ap-northeast-1" ]; $tablePrefix = "odm-"; $cacheDir = __DIR__ . "/ut/cache"; $isDev = true; $itemNamespace = 'BF\Mlib\ODM\Dynamodb\Ut'; // in practice, this usually looks like: My\Root\Namespace\Items $itemSrcDir = __DIR__ . "/ut"; // in practice, this usually points to src/Items directory $im = new ItemManager( $awsConfig, $tablePrefix, $cacheDir, $isDev ); $im->addNamespace( $itemNamespace, $itemSrcDir );
下面解释了每个参数的含义
注意:Item 类定义了 ODM 管理的项目类型。一些典型的例子包括:User、Order、GameRoom 和 Card
设置命令行工具
DynamoDb ODM 随附了一些非常有用的命令行工具,这些工具在开发过程中非常有帮助。您可以从 Composer 二进制目录调用此命令
$ ./vendor/bin/oasis-dynamodb-odm
您需要将应用程序的 ItemManager
注册到控制台工具,以便使用内置命令。这通过在调用目录下创建一个名为 odm-config.php 的文件来完成,内容如下
<?php use BF\Mlib\ODM\Dynamodb\Console\ConsoleHelper; // replace with file to your own project bootstrap require_once 'bootstrap.php'; // replace with your own mechanism to retrieve the item manager $itemManager = GetItemManager(); return new ConsoleHelper($itemManager);
详细使用方法请参阅后面的章节
映射
ODM 库的基本功能是将对象模型(即类)映射到数据库结构。DynamoDb ODM 提供了一种方便的方法,通过注解帮助建立这种映射。
<?php use BF\Mlib\ODM\Dynamodb\Annotations\Field; use BF\Mlib\ODM\Dynamodb\Annotations\Item; /** * @Item( * table="users", * primaryIndex={"id"} * ) */ class User { /** * @var int * @Field(type="number") */ protected $id; /** * @var string * @Field(type="string") */ protected $name; }
上面的类声明了一个简单的 User 模型,该模型将被映射到 DynamoDb 表 "users"(可能带有前缀)。下面的注释将解释这些注解
Item
您想使用 ODM 保存到数据库的每个 PHP 对象都称为 "Item"。为了将对象描述为项,我们必须描述该对象所属的类。
带有 @Item 注解的类将由 ItemManager 管理。Item 接受以下属性
- table:对象的表名
- primaryIndex:主键,可以是键的数组,或一个 @Index 注解对象
- globalSecondaryIndices:全局二级索引的数组;全局二级索引可以是键的数组,或一个 @Index 注解对象
- localSecondaryIndices:局部二级索引的数组;局部二级索引可以是键的数组,或一个 @Index 注解对象
- repository:存储库类名;默认情况下,使用
\BF\Mlib\ODM\Dynamodb\ItemRepository
- projected:此项目是否仅投影。投影项目不可更新(允许删除操作)。当读取(即获取/查询/扫描)投影项目时,只从 DynamoDb 中获取此项目的属性。
字段
将 PHP 类转换为 Item 的下一步是将它的属性映射到 DynamoDb 中的属性。
我们使用 @Field 注解来描述 DynamoDb 属性的类属性。@Field 注解支持以下属性
- 类型:属性的类型,可以是以下之一
- 字符串(默认)
- 数字
- 二进制
- 布尔值
- 空值
- 列表
- 映射
- 名称:DynamoDb属性名称,如果与属性名称不同。默认值为
null
,表示属性键与属性名称相同。
分区哈希键
分区哈希键是查询中用作哈希键的域的扩展。有些情况下,您只想对该域的单个值(或非常少的值)进行查询。DynamoDB的本质将只利用分配的读取容量的一小部分,从而限制系统性能。但是,通过使用该域的分区哈希键,原始域的每个值在分区哈希键域中都将有一组映射值。通过并行查询这些分区值(请参阅多查询),在此用例中,您的查询性能应该会显着提高。
我们使用@PartitionedHashKey注解来描述分区哈希键域。支持的属性有
- baseField:原始字段名称
- hashField:用作哈希源的值所在的字段,始终使用分布良好的字段作为哈希字段(例如,项目的唯一ID)
- size:分区大小,默认为16
索引
当声明不同的索引时,我们可以使用@Index注解来使文档块更易于阅读。一个@Index由两个键组成
- hash:哈希键名称
- range:范围键名称,如果没有此索引的范围键,则留空
- name:索引名称,如果您希望ODM为您自动生成一个,则留空。(注意:主索引不需要名称)
以下是我们向其中添加全局二级索引的User类声明
/** * @Item( * table="users", * primaryIndex={"id"}, * globalSecondaryIndices={ * @Index(hash="class", range="age", name="class-age-gsi") * } * ) */ class User { // ... /** * @var string * @Field() */ protected $class; /** * @var int * @Field(type="number") */ protected $age; }
检查和设置
字段可以被声明为检查和设置字段,使用@Field注解的"cas"属性。
检查和设置字段是ODM用来确保在相同时间没有不同的工作者更新/插入单个项的域。
"cas"属性的值可以是以下之一
- 禁用:这是默认值,带有"cas"禁用的字段在更新/插入项时将不会进行检查
- 启用:在更新项时将检查此字段的旧值。在插入项时,此字段必须具有NULL值或不存在。
- 时间戳:这是一种特殊的启用cas属性。每次更新/插入项时,此字段的值都会自动设置为当前时间戳。
注意:只有在调用
ItemManger#flush()
时才会执行检查和设置验证。不满足检查和设置条件将导致抛出BF\Mlib\ODM\Dynamodb\Exceptions\DataConsistencyException
异常。
与对象一起工作
ODM中的所有对象(项)都受管理。对对象的操作像对象级事务一样进行管理。一旦对象被管理,无论是作为新对象持久化还是从数据库中检索,其管理状态都会存储在ItemManager中。对对象的任何更改都会记录在内存中。然后可以通过在ItemManager上调用ItemManager#flush()
方法来提交对象更改。
可以通过调用ItemManager#clear()
手动清除ItemManager。然而,尚未提交的任何更改都将丢失。
注意:理解以下内容非常重要,只有调用
ItemManager#flush()
才会对数据库进行写操作。其他任何方法,如ItemManager#persist($item)
或ItemManager#remove($item)
,都只是通知 ItemManager 在刷新时执行这些操作。不调用ItemManager#flush()
将导致该请求期间的所有更改丢失。
持久化项
可以通过传递给 ItemManager#persist($item)
方法来使项持久化。通过在某个项上应用持久化操作,该项变为 被管理,这意味着其持久化现在由 ItemManager 管理。结果,在调用 ItemManager#flush()
时,此类项的持久化状态将与数据库正确同步。
示例
<?php /** @var ItemManger $im */ $user = new User(); $user->setName('Mr.Right'); $im->persist($user); $im->flush();
移除项
可以通过传递给 ItemManager#remove($item)
方法从持久化存储中移除项。通过在某个项上应用移除操作,该项变为 已移除,这意味着在调用 ItemManager#flush()
后,其持久化状态将被删除。
示例
<?php /** @var ItemManger $im */ /** @var User $user */ $im->remove($user); $im->flush();
断开项连接
可以通过在项上调用 ItemManager#detach($item)
方法将其从 ItemManager 断开连接,从而不再由其管理。断开连接的项(如果有的话)所做的更改(包括移除项),在项断开连接后不会同步到数据库。
DynamoDb ODM 不会保留对已断开连接项的任何引用。
示例
<?php /** @var ItemManger $im */ /** @var User $user */ $im->detach($user); $user->setName('Mr.Left'); $im->flush(); // changes to $user will not be synchronized
与数据库同步
ItemManager 的 flush()
调用将持久项的状态与数据库同步。同步涉及将任何更新写入持久项的数据库。当调用 ItemManager#flush()
时,ODM 会检查所有管理的、新的和已删除的项,并将执行以下操作
- 在数据库中创建新对象
- 更新数据库中已管理项的更改属性
- 从数据库中删除已删除的项
获取项
DynamoDb ODM 提供以下方法来获取持久对象,这些方法的强大性和灵活性依次增加。您应始终从满足您需求的最简单方法开始。
通过主索引
获取持久对象的最基本方法是使用 ItemManager#get($itemClass, $primayKeys)
方法通过其主索引。以下是一个示例
<?php /** @var ItemManager $im */ $user = $im->get(User::class, ["id" => 1]);
返回值是找到的项实例,或者在给定标识符找不到实例时为 null。
本质上,ItemManager#get()
只是以下操作的快捷方式
/** @var ItemManager $im */ /** @var ItemRepository $userRepo */ $userRepo = $im->getRepository(User::class); $user = $userRepo->get(["id" => 1]);
通过可查询索引上的简单条件
要基于简单条件查询一个或多个项,请在存储库上使用 ItemManager#query()
和 ItemManager#queryAndRun()
方法,如下所示
/** @var ItemManager $im */ /** @var ItemRepository $userRepo */ $userRepo = $im->getRepository(User::class); /** @var Users[] $users */ $users = $userRepo->query( "#class = :class AND #age >= :minAge", [ ":class" => "A", ":minAge" => 25, ], "class-age-index" );
注意:简单条件是仅使用一个索引的条件。如果使用的索引包含 哈希键 和 范围键,则只有在 哈希键 也出现在条件中时,才能使用 范围键。此外,只能对 哈希键 执行等于测试操作。
通过分区哈希键的多查询
要基于分区哈希键查询一个或多个项,请在存储库上使用 ItemManager#multiQueryAndRun()
方法,如下所示
/** @var ItemManager $im */ /** @var ItemRepository $userRepo */ $userRepo = $im->getRepository(User::class); /** @var Users[] $users */ $users = $userRepo->multiQueryAndRun( function ($item) { // each item returned can be accessed here in the callback }, "classPartition", // PartitionedHashKey field name "A", // value expected in the base field (not the partition field) "#age >= :minAge", // only range conditions here [ ":minAge" => 25, ], "class-partition-age-index" // index for PartitionedHashKey );
通过非可查询索引上的过滤器
要查询没有相关索引的一个或多个项,请在存储库上使用 ItemManager#scan()
和 ItemManager#scanAndRun()
方法,如下所示
/** @var ItemManager $im */ /** @var ItemRepository $userRepo */ $userRepo = $im->getRepository(User::class); /** @var Users[] $users */ $users = $userRepo->scan( "#class = :class AND #age >= :minAge AND #name = :name", [ ":class" => "A", ":minAge" => 25, ":name" => "John", ], );
使用命令行工具
DynamoDb ODM 与库一起提供可执行工具。安装后,以下内置命令有助于您管理项的数据库模式
创建
$ ./vendor/bin/oasis-dynamodb-odm odm:schema-tool:create
创建命令将遍历所有管理的项并创建相应的表。所有主索引、LSIs 和 GSIs 都会创建。
注意:如果在同一前缀下已存在具有相同名称的表,将抛出异常。在这种情况下不会创建任何表。
注意:如果您想跳过创建现有表(即只创建不存在的表),可以使用“--skip-existing-table”选项
更新
$ ./vendor/bin/oasis-dynamodb-odm odm:schema-tool:update
更新命令实际上是创建命令的一个更强大(但也更慢)的版本。它会检查所有管理项,如果表不存在则创建表。此外,如果表已存在但定义了不同的GSIs,更新命令将相应地更新GSIs。
注意:由于DynamoDb的特性,在表已创建的情况下无法更新主索引或LSI。在开发环境中,建议在需要时删除表并重新创建它们。
注意:如果您只想查看数据库模式的变化而不执行实际更新,可以在命令行中指定“--dry-run”选项。程序将仅提示可能的变化,而不会实际执行。
删除
$ ./vendor/bin/oasis-dynamodb-odm odm:schema-tool:drop
删除命令将删除与管理项相关的所有表。**不要**在生产环境中运行此命令!