maketok/datamigration
Composer 安装命令:
composer require maketok/datamigration
包简介
Maketok Data-Migration engine
README 文档
README
This package is aimed at migrating large chunks of data across different resources.
Some of the influences:
It's perfect to plan and execute a complex import or export. It also can be used as a transport tool to migrate your data from one structure to another. The unit (workers) structure allows it to parse a complex import file and extract a multi-level data structure from it.
The same's true for reverse process as well: the multi-level data structure can be inserted into a single file.
Installation
Use composer to include it in your project:
composer require maketok/datamigration
Examples
There are few examples in tests/integration/QueueWorkflowTest integration test.
Here's the typical uses.
Import
Import customers and addresses from flat CSV file.
| name | age | street | city | zip | |
|---|---|---|---|---|---|
| bart22@example.com | Bart Robbinson | 32 | 20 Chestnut Terrace | New York | 07003 |
| vilkron@aim.at.com | Kale D | 15 | 123 Manson | LA | 90023 |
| 111 Dale str. | Chicago | 60333 |
use Maketok\DataMigration\MapInterface; use Maketok\DataMigration\QueueWorkflow; use Maketok\DataMigration\Unit\SimpleBag; use Maketok\DataMigration\Unit\Type\Unit; use Maketok\DataMigration\Storage\Db\ResourceHelperInterface; use Maketok\DataMigration\Action\Type\CreateTmpFiles; use Maketok\DataMigration\Action\Type\Load; use Maketok\DataMigration\Action\Type\Move; use Maketok\DataMigration\Input\Shaper\Processor\Nulls; $customerUnit = new Unit('customers'); $customerUnit->setTable('customers'); $customerUnit->setMapping([ 'id' => 'map.customer_id' // ExpressionLanguage is used to interpret string expressions 'email' => 'mail.email', // closure or any other callable is also acceptable 'name' => function (MapInterface $map) { return $map['name']; }, 'age' => 'map.age', ]); /* * the is_entity condition resolves whether * unit should consider current row as the entity * some utility functions are available in * Maketok\DataMigration\Expression\HelperExpressionsProvider */ $customerUnit->setIsEntityCondition("trim(map.email) is not empty"); /* * the contributions is the way for unit to * add some data into general pool for every other unit to use * * This is the logic for assigning customer_id * First it checks if it exists in the pre-compiled Hashmap * If it does not, it's calling for frozen increment for "new_customer_id" key * and assign the last increment id if it's non existent * The frozenIncr is different from incr in that it's incremented only once * is_entity condition resolves for current row * So it's perfect for incrementing "parent" entities */ $customerUnit->addContribution(function ( MapInterface $map, ResourceHelperInterface $resource, array $hashmaps ) { if (isset($hashmaps['email-id'][trim($map->email)])) { $map['customer_id'] = $hashmaps['email-id'][trim($map->email)]; } else { $map['customer_id'] = $map->frozenIncr( 'new_customer_id', $resource->getLastIncrementId('customers') ) } }); $addressUnit = new Unit('addresses'); $addressUnit->setTable('addresses'); $addressUnit->setMapping([ 'id' => 'map.incr('address_id', resource.getLastIncrementId('addresses'))' 'street' => 'map.street', 'city' => 'map.city', 'zip' => 'map.zip', 'parent_id' => 'map.customer_id', ]); $addressUnit->setParent($customerUnit); $bag = new SimpleBag(); $bag->addSet([$customerUnit, $addressUnit]); /* * Last but not least, since we're using CSV file, we need a Shaper * instance to shape up our flat file before feeding it to CreateTmpFiles action */ $input = new Csv($fname, 'r', new Nulls($bag, new ArrayMap(), $this->getLanguageAdapter())); $workflow = new QueueWorkflow($config, $result); $workflow->add(new CreateTmpFiles($bag, $config, $languageAdapter, $input, new ArrayMap(), $helperResource)); $workflow->add(new Load($bag, $config, $resource)); $workflow->add(new Move($bag, $config, $resource)); $workflow->execute();
Export
We have 3 DB tables for customers and their addresses.
customer
| id | age | |
|---|---|---|
| 1 | bart22@example.com | 32 |
| 2 | vilkron@aim.at.com | 15 |
customer_data
| id | parent_id | firstname | lastname |
|---|---|---|---|
| 1 | 1 | Bart | Robinson |
| 2 | 2 | Kale | Dager |
address
| id | customer_id | street | city | zip |
|---|---|---|---|---|
| 1 | 1 | 20 Chestnut Terrace | New York | 07003 |
| 2 | 1 | 123 Manson | LA | 90023 |
| 3 | 2 | 111 Dale str. | Chicago | 60333 |
We want to get next output:
customers.csv
| name | age | street | city | zip | |
|---|---|---|---|---|---|
| bart22@example.com | Bart Robbinson | 32 | 20 Chestnut Terrace | New York | 07003 |
| vilkron@aim.at.com | Kale D | 15 | 123 Manson | LA | 90023 |
| 111 Dale str. | Chicago | 60333 |
use Maketok\DataMigration\MapInterface; use Maketok\DataMigration\QueueWorkflow; use Maketok\DataMigration\Unit\SimpleBag; use Maketok\DataMigration\Unit\Type\Unit; use Maketok\DataMigration\Storage\Db\ResourceHelperInterface; use Maketok\DataMigration\Action\Type\AssembleInput; use Maketok\DataMigration\Action\Type\Load; use Maketok\DataMigration\Action\Type\Move; use Maketok\DataMigration\Input\Shaper\Processor\Nulls; $customerUnit = new Unit('customers'); $customerUnit->setTable('customer'); $customerUnit->setMapping([ 'id' => 'map.customer_id' 'email' => 'mail.email', 'age' => 'map.age', ]); $customerUnit->setIsEntityCondition("trim(map.email) is not empty"); $customerUnit->addContribution("map.offsetSet( 'customer_id', (isset(hashmaps['email-id'][trim(map.email)]) ? hashmaps['email-id'][trim(map.email)] : map.frozenIncr( 'new_customer_id', resource.getLastIncrementId('customer') ) ) )"); $customerUnit->setReversedConnection([ 'customer_id' => 'id', ]); $customerUnit->setReversedMapping([ 'email' => 'map.email', 'age' => 'map.age', ]); $customerDataUnit = new Unit('customer_data'); $customerDataUnit->setTable('customer_data'); $customerDataUnit->setMapping([ 'id' => 'map.incr('customer_data_id', resource.getLastIncrementId('customer_data'))' 'parent_id' => 'map.customer_id' 'firstname' => 'map.firstname', 'lastname' => 'map.lastname', ]); $customerDataUnit->addContribution("map.offsetSet( 'complexName', explode(' ', map.name) )"); $customerDataUnit->addContribution("map.offsetSet( 'firstname', (count(map.complexName) >= 2 && isset(map.complexName[0]) ? map.complexName[0] : map.name) )"); $customerDataUnit->addContribution("map.offsetSet( 'lastname', (count(map.complexName) >= 2 && isset(map.complexName[1]) ? map.complexName[1] : '') )"); $customerDataUnit->setReversedConnection([ 'customer_id' => 'parent_id', ]); $customerDataUnit->setReversedMapping([ 'name' => 'map.firstname ~ " " ~ map.lastname', ]); $customerUnit->addSibling($customerDataUnit); $addressUnit = new Unit('addresses'); $addressUnit->setTable('address'); $addressUnit->setMapping([ 'id' => 'map.incr('address_id', resource.getLastIncrementId('address'))' 'customer_id' => 'map.customer_id', 'street' => 'map.street', 'city' => 'map.city', 'zip' => 'map.zip', ]); $addressUnit->setReversedConnection([ 'customer_id' => 'customer_id', ]); $addressUnit->setReversedMapping([ 'street' => 'map.street', 'city' => 'map.city', 'zip' => 'map.zip', ]); $addressUnit->setParent($customerUnit); $bag = new SimpleBag(); $bag->addSet([$customerUnit, $customerDataUnit, $addressUnit]); $input = new Csv($fname, 'w', new Nulls($bag, new ArrayMap(), $this->getLanguageAdapter())); $result = new Result(); $workflow = new QueueWorkflow($this->config, $result); $workflow->add(new ReverseMove($bag, $config, $resource)); $workflow->add(new Dump($bag, $config, $resource)); $workflow->add(new AssembleInput($bag, $config, $languageAdapter, $input, new ArrayMap())); $workflow->execute();
FAQ
maketok/datamigration 适用场景与选型建议
maketok/datamigration 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 29.01k 次下载、GitHub Stars 达 4, 最近一次更新时间为 2015 年 07 月 28 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「data」 「import」 「migration」 「generation」 「export」 「maketok」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 maketok/datamigration 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 maketok/datamigration 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 maketok/datamigration 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Shoot aims to make providing data to your templates more manageable
Adds the EDTF data type to Wikibase
A simple library that allows transform any kind of data to native php data or whatever
Parse use statements for a reflection object
Tool for copying data from a production database to a dev database. Also useful for making backups of production databases.
A fork of konnco/filament-import with support of Laravel 11 since the default importer of Filament 3 is nonsense for basic use case.
统计信息
- 总下载量: 29.01k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 4
- 点击次数: 11
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2015-07-28