tobento / service-repository-storage
存储库实现。
Requires
- php: >=8.0
- tobento/service-collection: ^1.0.5
- tobento/service-dater: ^1.0.1
- tobento/service-iterable: ^1.0
- tobento/service-repository: ^1.0
- tobento/service-storage: ^1.2.1
- tobento/service-support: ^1.0
Requires (Dev)
- phpunit/phpunit: ^9.5
- tobento/service-container: ^1.0
- tobento/service-database-storage: ^1.0
- tobento/service-filesystem: ^1.0
- tobento/service-migration: ^1.0.5
- vimeo/psalm: ^4.0
Suggests
- tobento/service-database-storage: Support for migration
- tobento/service-migration: Support for migration
README
目录
入门
使用此命令添加正在运行的仓库存储服务项目的最新版本。
composer require tobento/service-repository-storage
需求
- PHP 8.0 或更高版本
亮点
- 框架无关,可与其他任何项目一起使用
- 解耦设计
文档
查看其可用的存储 存储服务 - 存储。
查看其文档 仓库服务。
存储仓库
要创建存储仓库,只需扩展 StorageRepository::class
您还可以查看 具有列的仓库 部分,以使用列创建仓库。
use Tobento\Service\Repository\RepositoryInterface; use Tobento\Service\Repository\ReadRepositoryInterface; use Tobento\Service\Repository\WriteRepositoryInterface; use Tobento\Service\Repository\Storage\StorageRepository; use Tobento\Service\Repository\Storage\StorageEntityFactoryInterface; use Tobento\Service\Storage\InMemoryStorage; use Tobento\Service\Storage\Tables\Tables; class ProductRepository extends StorageRepository { // } $repository = new ProductRepository( storage: new InMemoryStorage( items: [], tables: (new Tables())->add('products', ['id', 'sku', 'price'], 'id') ), table: 'products', // specify which storage table should be used. entityFactory: null, // null|StorageEntityFactoryInterface ); var_dump($repository instanceof RepositoryInterface); // bool(true) var_dump($repository instanceof ReadRepositoryInterface); // bool(true) var_dump($repository instanceof WriteRepositoryInterface); // bool(true)
默认情况下,读取和写入方法将根据调用方法返回以下类型
Tobento\Service\Storage\ItemInterface::class
存储 - ItemInterfaceTobento\Service\Storage\ItemsInterface::class
存储 - ItemsInterfacenull
您可以通过指定自定义的 存储实体工厂 通过 entityFactory
参数返回自定义实体。
存储读取仓库
要创建存储读取仓库,只需扩展 StorageReadRepository::class
您还可以查看 具有列的仓库 部分,以使用列创建仓库。
use Tobento\Service\Repository\ReadRepositoryInterface; use Tobento\Service\Repository\Storage\StorageReadRepository; use Tobento\Service\Repository\Storage\StorageEntityFactoryInterface; use Tobento\Service\Storage\InMemoryStorage; use Tobento\Service\Storage\Tables\Tables; class ProductReadRepository extends StorageReadRepository { // adding custom find methods } $repository = new ProductReadRepository( storage: new InMemoryStorage( items: [ 'products' => [ 1 => ['id' => 1, 'sku' => 'paper', 'price' => 1.2], 2 => ['id' => 2, 'sku' => 'pen', 'price' => 1.8], 3 => ['id' => 3, 'sku' => 'pencil', 'price' => 1.5], ], ], tables: (new Tables())->add('products', ['id', 'sku', 'price'], 'id') ), table: 'products', entityFactory: null, // null|StorageEntityFactoryInterface ); var_dump($repository instanceof ReadRepositoryInterface); // bool(true)
默认情况下,find 方法将根据调用方法返回以下类型
Tobento\Service\Storage\ItemInterface::class
存储 - ItemInterfaceTobento\Service\Storage\ItemsInterface::class
存储 - ItemsInterfacenull
您可以通过指定自定义的 存储实体工厂 通过 entityFactory
参数返回自定义实体。
findById
use Tobento\Service\Storage\ItemInterface; $entity = $repository->findById(id: 2); var_dump($entity instanceof ItemInterface); // bool(true) var_dump($entity->get('sku')); // string(3) "pen" $entity = $repository->findById(id: 5); var_dump($entity); // NULL
您可以查看 存储服务 - ItemInterface 的文档。
findByIds
use Tobento\Service\Storage\ItemsInterface; use Tobento\Service\Storage\ItemInterface; $entities = $repository->findByIds(1, 2, 8); var_dump($entities instanceof ItemsInterface); // bool(true) var_dump($entities->count()); // int(2) foreach($entities as $entity) { var_dump($entity instanceof ItemInterface); // bool(true) }
您可以查看 存储服务 - ItemsInterface 的文档。
您可以查看 存储服务 - ItemInterface 的文档。
findOne
use Tobento\Service\Storage\ItemInterface; $entity = $repository->findOne(where: [ 'sku' => 'pen', ]); var_dump($entity instanceof ItemInterface); // bool(true) var_dump($entity->get('sku')); // string(3) "pen" $entity = $repository->findOne(where: [ 'sku' => 'foo', ]); var_dump($entity); // NULL
您可以查看 Where参数 支持的参数。
您可以查看 存储服务 - ItemInterface 的文档。
findAll
use Tobento\Service\Storage\ItemsInterface; use Tobento\Service\Storage\ItemInterface; $entities = $repository->findAll(where: [ 'price' => ['>' => 1.3], ]); var_dump($entities instanceof ItemsInterface); // bool(true) var_dump($entities->count()); // int(2) foreach($entities as $entity) { var_dump($entity instanceof ItemInterface); // bool(true) } $entities = $repository->findAll( where: [ 'price' => [ '>' => 1.3, '<' => 1.6, ], 'sku' => ['like' => 'pe%'], ], orderBy: [ 'sku' => 'DESC', // or 'ASC' ], limit: 20, // (number) // limit: [20, 5], // [20(number), 5(offset)] ); var_dump($entities->count()); // int(1)
您可以查看 Where参数 支持的参数。
您可以查看 存储服务 - ItemsInterface 的文档。
您可以查看 存储服务 - ItemInterface 的文档。
存储写入仓库
要创建存储写入仓库,只需扩展 StorageWriteRepository::class
您还可以查看 具有列的仓库 部分,以使用列创建仓库。
use Tobento\Service\Repository\WriteRepositoryInterface; use Tobento\Service\Repository\Storage\StorageWriteRepository; use Tobento\Service\Repository\Storage\StorageEntityFactoryInterface; use Tobento\Service\Storage\InMemoryStorage; use Tobento\Service\Storage\Tables\Tables; class ProductWriteRepository extends StorageWriteRepository { // you may add custom write methods } $repository = new ProductWriteRepository( storage: new InMemoryStorage( items: [ 'products' => [ 1 => ['id' => 1, 'sku' => 'paper', 'price' => 1.2], 2 => ['id' => 2, 'sku' => 'pen', 'price' => 1.8], 3 => ['id' => 3, 'sku' => 'pencil', 'price' => 1.5], ], ], tables: (new Tables())->add('products', ['id', 'sku', 'price'], 'id') ), table: 'products', entityFactory: null, // null|StorageEntityFactoryInterface ); var_dump($repository instanceof WriteRepositoryInterface); // bool(true)
默认情况下,方法将根据调用方法返回以下类型
Tobento\Service\Storage\ItemInterface::class
存储 - ItemInterfaceTobento\Service\Storage\ItemsInterface::class
存储 - ItemsInterfacenull
您可以通过指定自定义的 存储实体工厂 通过 entityFactory
参数返回自定义实体。
create
use Tobento\Service\Storage\ItemInterface; $createdEntity = $repository->create(attributes: [ 'sku' => 'scissors', ]); var_dump($createdEntity instanceof ItemInterface); // bool(true) var_dump($createdEntity->all()); // array(2) { ["sku"]=> string(8) "scissors" ["id"]=> int(4) }
您可以查看 存储服务 - ItemInterface 的文档。
updateById
use Tobento\Service\Storage\ItemInterface; use Tobento\Service\Repository\RepositoryUpdateException; $updatedEntity = $repository->updateById( id: 2, attributes: [ 'price' => 2.5, ] ); var_dump($updatedEntity instanceof ItemInterface); // bool(true) var_dump($updatedEntity->all()); // array(2) { ["sku"]=> string(8) "scissors" ["id"]=> int(4) }
如果存储表未指定主键或要更新的实体不存在,则此方法将抛出 RepositoryUpdateException::class
异常。
您可以查看 存储服务 - ItemInterface 的文档。
update
use Tobento\Service\Storage\ItemsInterface; use Tobento\Service\Storage\ItemInterface; $updatedEntities = $repository->update( where: [ 'id' => ['>' => 1], ], attributes: [ 'price' => 2.5, ], ); var_dump($updatedEntities instanceof ItemsInterface); // bool(true) var_dump($updatedEntities->count()); // int(2) foreach($updatedEntities as $entity) { var_dump($entity instanceof ItemInterface); // bool(true) }
您可以查看 Where参数 支持的参数。
您可以查看 存储服务 - ItemsInterface 的文档。
您可以查看 存储服务 - ItemInterface 的文档。
deleteById
use Tobento\Service\Storage\ItemInterface; use Tobento\Service\Repository\RepositoryDeleteException; $deletedEntity = $repository->deleteById(id: 2); var_dump($deletedEntity instanceof ItemInterface); // bool(true) var_dump($deletedEntity->all()); // array(3) { ["id"]=> int(2) ["sku"]=> string(3) "pen" ["price"]=> float(1.8) }
此方法如果存储表没有指定主键或要删除的实体不存在,将会抛出RepositoryDeleteException::class
异常。
您可以查看 存储服务 - ItemInterface 的文档。
删除
use Tobento\Service\Storage\ItemsInterface; use Tobento\Service\Storage\ItemInterface; $deletedEntities = $repository->delete(where: [ 'id' => ['>' => 1], ]); var_dump($deletedEntities instanceof ItemsInterface); // bool(true) var_dump($deletedEntities->count()); // int(2) foreach($deletedEntities as $entity) { var_dump($entity instanceof ItemInterface); // bool(true) }
您可以查看 Where参数 支持的参数。
您可以查看 存储服务 - ItemsInterface 的文档。
您可以查看 存储服务 - ItemInterface 的文档。
Where参数
以下where子句被支持(对于所有带有where参数的读写方法)
$entities = $repository->findAll(where: [ 'sku' => 'pen', // is equal to: 'sku' => ['=' => 'pen'], 'sku' => ['!=' => 'pen'], 'sku' => ['null'], 'sku' => ['not null'], 'price' => ['>' => 1.5], 'price' => ['<' => 1.5], 'price' => ['>=' => 1.5], 'price' => ['<=' => 1.5], 'price' => ['<>' => 1.5], 'price' => ['<=>' => 1.5], 'price' => ['between' => [2, 5]], 'price' => ['not between' => [2, 5]], 'id' => ['in' => [2,5,6]], 'id' => ['not in' => [2,5,6]], // Finds any values that (not) start with "a" 'title' => ['like' => 'a%'], 'title' => ['not like' => 'a%'], // Finds any values that (not) end with "a" 'title' => ['like' => '%a'], 'title' => ['not like' => '%a'], // Finds any values that have (not) "a" in any position 'title' => ['like' => '%a%'], 'title' => ['not like' => '%a%'], // Json specific: 'options->color' => 'blue', 'options->colors' => ['contains' => 'blue'], 'options->colors' => ['contains' => ['blue']], 'options->color' => ['contains key'], ]);
存储实体工厂
您可以通过存储仓库、存储读取仓库或存储写入仓库来创建自定义实体工厂以返回自定义实体。
要创建自定义实体工厂,只需扩展EntityFactory::class
并调整createEntityFromArray
方法
use Tobento\Service\Repository\Storage\EntityFactory; use Tobento\Service\Repository\Storage\StorageEntityFactoryInterface; use Tobento\Service\Repository\EntityFactoryInterface; use Tobento\Service\Storage\ItemInterface; class ProductFactory extends EntityFactory { public function createEntityFromArray(array $attributes): Product { // Process the columns reading: $attributes = $this->columns->processReading($attributes); // Create entity: return new Product( id: $attributes['id'] ?? 0, sku: $attributes['sku'] ?? '', ); } } class Product { public function __construct( public readonly int $id, public readonly string $sku, ) {} } $productFactory = new ProductFactory(); $productFactory->setColumns([]); // will be set by the storage var_dump($productFactory instanceof StorageEntityFactoryInterface); // bool(true) var_dump($productFactory instanceof EntityFactoryInterface); // bool(true) $product = $productFactory->createEntityFromArray([ 'id' => 1, 'sku' => 'pen', ]); var_dump($product); // object(Product)#4 (2) { ["id"]=> int(1) ["sku"]=> string(3) "pen" }
具有列的仓库
具有列的存储仓库有以下优点
- 在读写时将值转换为原始类型
- 指定读取器和写入器来处理转换
- 根据列创建数据库迁移
use Tobento\Service\Repository\Storage\StorageRepository; use Tobento\Service\Repository\Storage\Column; use Tobento\Service\Storage\InMemoryStorage; class ProductRepository extends StorageRepository { // } $repository = new ProductRepository( storage: new InMemoryStorage(items: []), table: 'products', // specify the columns: columns: [ Column\Id::new(), Column\Text::new('sku'), Column\Text::new('title') ->read(fn (string $value, array $attributes): string => ucfirst($value)) ->write(fn (string $value, array $attributes, string $action): string => ucfirst($value)), Column\Boolean::new('active'), ], );
您可以通过使用configureColumns
方法在其类上指定列
use Tobento\Service\Repository\Storage\StorageRepository; use Tobento\Service\Repository\Storage\Column\ColumnsInterface; use Tobento\Service\Repository\Storage\Column\ColumnInterface; use Tobento\Service\Repository\Storage\Column; use Tobento\Service\Storage\InMemoryStorage; class ProductRepository extends StorageRepository { /** * Returns the configured columns. * * @return iterable<ColumnInterface>|ColumnsInterface */ protected function configureColumns(): iterable|ColumnsInterface { return [ Column\Id::new(), Column\Text::new('sku'), Column\Text::new('title') ->read(fn (string $value, array $attributes): string => ucfirst($value)) ->write(fn (string $value, array $attributes, string $action): string => ucfirst($value)), Column\Boolean::new('active'), ]; } } $repository = new ProductRepository( storage: new InMemoryStorage(items: []), table: 'products', );
列的常用方法
类型
在type
方法上设置的参数仅用于迁移目的。
use Tobento\Service\Repository\Storage\Column\Text; use Tobento\Service\Repository\Storage\Column\Int; $column = Text::new(name: 'name') ->type(length: 150, nullable: false, default: 'foo', parameters: ['charset' => 'utf8mb4']); $column = Int::new(name: 'name') ->type( length: 20, unsigned: true, index: ['name' => 'index_name', 'column' => 'name', 'unique' => true, 'primary' => true], ); $column = Float::new(name: 'name', type: 'decimal') ->type(precision: 10, scale: 0);
有关更多详细信息,请查看服务数据库 - 列工厂的createColumnFromArray
方法。
有关更多详细信息,请查看服务数据库 - 索引工厂的createIndexFromArray
方法。
读取
您可以使用读取方法来指定读取器(可调用)。当尝试检索值时,仓库将自动调用读取器。
use Tobento\Service\Repository\Storage\Column\Text; $column = Text::new(name: 'name') ->read(fn (string $value, array $attributes): string => ucfirst($value));
在传递给读取器之前,值将被转换为它的列类型!
写入
您可以使用写入方法来指定写入器(可调用)。当尝试写入值时,仓库将自动调用写入器。只有在任何写入方法上存在属性时,写入器才会被调用。如果您想始终调用写入器,请查看强制写入部分。
use Tobento\Service\Repository\Storage\Column\Text; $column = Text::new(name: 'name') ->write(fn (string $value, array $attributes, string $action): string => ucfirst($value)); // $action = the action name processed such as 'create' or 'update'
在传递给写入器之前,值将被转换为它的列类型!
强制写入
您可以使用forceWriting
方法来指定是否要强制写入,这意味着即使在任何写入方法上未传递属性,写入器也会始终被调用。
use Tobento\Service\Repository\Storage\Column\Text; $column = Text::new(name: 'name') ->forceWriting() ->write(fn (string $value, array $attributes, string $action): string => ucfirst($value));
可存储
use Tobento\Service\Repository\Storage\Column\Text; $column = Text::new(name: 'name') ->storable(false);
列
布尔值
use Tobento\Service\Repository\Storage\Column\Boolean; $column = Boolean::new(name: 'active'); $column = Boolean::new(name: 'active') ->type(default: true);
日期时间
use Tobento\Service\Repository\Storage\Column\Datetime; $column = Datetime::new(name: 'created_at'); // with datetime type (default): $column = Datetime::new(name: 'created_at', type: 'datetime') ->type(nullable: true); // with date type: $column = Datetime::new(name: 'created_at', type: 'date') ->type(nullable: true); // with time type: $column = Datetime::new(name: 'created_time', type: 'time') ->type(nullable: true); // with timestamp type: $column = Datetime::new(name: 'created_ts', type: 'timestamp') ->type(nullable: true);
读取
您可以使用读取方法来转换您的值。如果不指定读取方法,则值仅转换为字符串。
use Tobento\Service\Repository\Storage\Column\Datetime; use Tobento\Service\Dater\DateFormatter; use DateTimeImmutable; $column = Datetime::new(name: 'created_at'); $read = fn (mixed $value, array $attributes, DateFormatter $df) : DateTimeImmutable => $df->toDateTime(value: $value); $column = Datetime::new(name: 'created_at')->read($read);
有关更多详细信息,请查看Dater服务 - 日期格式化器。
写入
您可以使用写入方法来转换您的值。如果不指定写入方法,则值将转换为以下格式
- datetime类型:
Y-m-d H:i:s
- date类型:
Y-m-d
- time类型:
H:i:s
- timestamp类型:时间戳字符串
use Tobento\Service\Repository\Storage\Column\Datetime; use Tobento\Service\Dater\DateFormatter; $column = Datetime::new(name: 'created_at'); $write = fn (mixed $value, array $attributes, string $action, DateFormatter $df) : string => $df->format(value: $value, format: 'H:i:s'); $column = Datetime::new(name: 'created_at')->read($read);
有关更多详细信息,请查看Dater服务 - 日期格式化器。
autoCreate
如果您想在任何写入方法未传递值时自动创建日期,请使用autoCreate
方法。
use Tobento\Service\Repository\Storage\Column\Datetime; $column = Datetime::new(name: 'created_at')->autoCreate();
autoUpdate
如果您想在任何写入方法未传递值时自动更新日期,请使用autoUpdate
方法。
use Tobento\Service\Repository\Storage\Column\Datetime; $column = Datetime::new(name: 'updated_at')->autoUpdate();
浮点数
use Tobento\Service\Repository\Storage\Column\FloatCol; $column = FloatCol::new(name: 'name'); // with float type (default): $column = FloatCol::new(name: 'name', type: 'float') ->type(nullable: false, default: 0.5); // with double type: $column = FloatCol::new(name: 'name', type: 'double') ->type(nullable: false, default: 0.5); // with decimal type: $column = FloatCol::new(name: 'name', type: 'decimal') ->type(nullable: false, default: 0.5, precision: 10, scale: 0);
Id
use Tobento\Service\Repository\Storage\Column\Id; $column = Id::new(); // with name (default is id): $column = Id::new(name: 'some_id'); // with bigPrimary type (default): $column = Id::new(type: 'bigPrimary') ->type( length: 18, unsigned: true, index: ['name' => 'index_name', 'primary' => true], ); // with primary: $column = Id::new(type: 'primary') ->type( length: 5, unsigned: true, index: ['name' => 'index_name', 'primary' => true], );
整数
use Tobento\Service\Repository\Storage\Column\Integer; $column = Integer::new(name: 'name'); // with int type (default): $column = Integer::new(name: 'name', type: 'int') ->type(length: 11, unsigned: true, nullable: false, default: 0); // with tinyInt type: $column = Integer::new(name: 'name', type: 'tinyInt') ->type(length: 5, unsigned: true, nullable: false, default: 0); // with bigInt type: $column = Integer::new(name: 'name', type: 'bigInt') ->type(length: 200, unsigned: true, nullable: false, default: 0);
Json
use Tobento\Service\Repository\Storage\Column\Json; $column = Json::new(name: 'name'); $column = Json::new(name: 'name') ->type(nullable: false, default: ['foo', 'bar']);
文本
use Tobento\Service\Repository\Storage\Column\Text; $column = Text::new(name: 'sku'); // with string type (default): $column = Text::new(name: 'sku', type: 'string') ->type(length: 100, nullable: false, default: ''); // with char type: $column = Text::new(name: 'locale', type: 'char') ->type(length: 5, nullable: false, default: 'en'); // with text type: $column = Text::new(name: 'desc', type: 'text') ->type(nullable: false, default: 'lorem ipsum');
可翻译
use Tobento\Service\Repository\Storage\Column\Translatable; $column = Translatable::new(name: 'name'); // with string subtype (default): $column = Translatable::new(name: 'name', subtype: 'string') ->type(nullable: false) ->read(fn (string $value, array $attributes, string $locale): string => strtoupper($value)) ->write(fn (string $value, array $attributes, string $action, string $locale): string => strtoupper($value)); // with array subtype: $column = Translatable::new(name: 'name', subtype: 'array') ->type(nullable: false) ->read(fn (array $value, array $attributes, string $locale): array => $value) ->write(fn (array $value, array $attributes, string $action, string $locale): array => $value);
读取属性
读取后,根据其列子类型string
或array
创建一个StringTranslations::class
或ArrayTranslations::class
。
use Tobento\Service\Repository\Storage\Attribute\StringTranslations; $repository->locale('en'); $repository->locales('en', 'de', 'fr'); $repository->localeFallbacks(['de' => 'en']); $entity = $repository->findById(id: 2); var_dump($entity->get('title') instanceof StringTranslations); // bool(true) // The title on the current locale set on the repository: $title = (string)$entity->get('title'); // or: $title = $entity->get('title')->get(); // specific locale: $title = $entity->get('title')->get(locale: 'de'); // specific locale with default value // if fallback locale value does not exist: $title = $entity->get('title')->get(locale: 'fr', default: 'title'); // check if translation exists: var_dump($entity->get('title')->has(locale: 'de')); // bool(true) // returns all translations: var_dump($entity->get('title')->all(); // array(2) {["en"]=> string(5) "Title" ["de"]=> string(5) "Titel"}
use Tobento\Service\Repository\Storage\Attribute\ArrayTranslations; $repository->locale('en'); $repository->locales('en', 'de', 'fr'); $repository->localeFallbacks(['de' => 'en']); $entity = $repository->findById(id: 2); var_dump($entity->get('meta') instanceof ArrayTranslations); // bool(true) // The meta on the current locale set on the repository: $meta = $entity->get('meta')->get(); // array(1) {["color"]=> string(3) "red"} // specific locale: $meta = $entity->get('meta')->get(locale: 'de'); // array(1) {["color"]=> string(3) "rot"} // specific locale with default value // if fallback locale value does not exist: $meta = $entity->get('meta')->get(locale: 'fr', default: ['color' => 'rot']); // array(1) {["color"]=> string(3) "red"} // check if translation exists: var_dump($entity->get('title')->has(locale: 'de')); // bool(true) // returns all translations: var_dump($entity->get('meta')->all(); // array(2) {["en"]=> array(1) {["color"]=> string(3) "red"} ["de"]=> array(1) {["color"]=> string(3) "rot"}} // The meta color on the current locale set on the repository: $color = $entity->get('meta')->get(key: 'color'); // string(3) "red" // specific locale: $color = $entity->get('meta')->get(locale: 'de', key: 'color'); // string(3) "rot" // specific locale with default value // if fallback locale value does not exist: $color = $entity->get('meta')->get(locale: 'fr', key: 'color', default: ['color' => 'rot']); // string(3) "red" // check if translation exists: var_dump($entity->get('title')->has(locale: 'de', key: 'color')); // bool(true)
翻译
配置仓库的本地化
// current locale: $repository->locale('en'); // only the defined locales are used: $repository->locales('en', 'de', 'fr'); // fallbacks: $repository->localeFallbacks(['de' => 'en']);
Where参数翻译
翻译列的where子句(对于所有带有where参数的读写方法)
$entities = $repository->findAll(where: [ // query current locale set on the repository: 'title' => ['like' => 'pe%'], // query specific locale using json syntax: 'title->de' => ['like' => 'pe%'], // Array translations: // query current locale set on the repository: 'options->color' => 'red', // same as: options->en->color // query specific locale using json syntax: 'options->de->color' => 'red', ]);
写入翻译
create
$createEntity = $repository->create([ 'title' => [ 'en' => 'Title', 'de' => 'Titel', ], ]);
update
// updates all: $updatedEntity = $repository->updateById(2, [ 'title' => [ 'en' => 'Title', 'de' => 'Titel', ], ]); // updates specific locale using json syntax: $updatedEntity = $repository->updateById(2, [ 'title->de' => 'Title', ]); // Array translations: // updates specific locale using json syntax: $updatedEntity = $repository->updateById(2, [ 'options->de->color' => 'red', ]);
迁移
如果您已经设置了您的具有列的仓库,您可以使用迁移RepositoryAction::class
和RepositoryDeleteAction::class
从定义的列创建您的数据库迁移。
首先,您需要安装
composer require tobento/service-database-storage
composer require tobento/service-migration
迁移类的示例
use Tobento\Service\Repository\Storage\Migration\RepositoryAction; use Tobento\Service\Repository\Storage\Migration\RepositoryDeleteAction; use Tobento\Service\Migration\MigrationInterface; use Tobento\Service\Migration\ActionsInterface; use Tobento\Service\Migration\Action; use Tobento\Service\Migration\Actions; class UserMigration implements MigrationInterface { public function __construct( protected UserRepository $userRepository, ) {} /** * Return a description of the migration. * * @return string */ public function description(): string { return 'Users migration'; } /** * Return the actions to be processed on install. * * @return ActionsInterface */ public function install(): ActionsInterface { // you might check if repository is supported for the action: if (RepositoryAction::isSupportedRepository($this->userRepository)) { // create action } return new Actions( new RepositoryAction( repository: $this->userRepository, description: 'User migration', // you might set items to be migrated items: [ ['email' => 'demo@example.com'], ], ), // you might use the newOrNull method // if the defined repository is of any type. // If it is an unsupported repository // a Action\NullAction::class is created. RepositoryAction::newOrNull( repository: $this->userRepository, description: 'User migration', // you might set items to be migrated items: [ ['email' => 'demo@example.com'], ], ), // you might use the newOrFail method // if the defined repository is of any type. // If it is an unsupported repository // a Action\Fail::class is created. RepositoryAction::newOrFail( repository: $this->userRepository, description: 'User migration', // you might set items to be migrated items: [ ['email' => 'demo@example.com'], ], ), ); } /** * Return the actions to be processed on uninstall. * * @return ActionsInterface */ public function uninstall(): ActionsInterface { // you might check if repository is supported for the action: if (RepositoryDeleteAction::isSupportedRepository($this->userRepository)) { // create action } return new Actions( new RepositoryDeleteAction( repository: $this->userRepository, description: 'User migration', ), // you might use the newOrNull method // if the defined repository is of any type. // If it is an unsupported repository // a Action\NullAction::class is created. RepositoryDeleteAction::newOrNull( repository: $this->userRepository, description: 'User migration', ), // you might use the newOrFail method // if the defined repository is of any type. // If it is an unsupported repository // a Action\Fail::class is created. RepositoryDeleteAction::newOrFail( repository: $this->userRepository, description: 'User migration', ), ); } }
您可以查看迁移服务获取更多详细信息。