dia-nz/importexport

对SilverStripe的批量加载和导出功能的升级

维护者

详细信息

github.com/DIA-NZ/importexport

来源

安装: 210

依赖项: 0

建议者: 0

安全: 0

星级: 0

关注者: 1

分支: 34

类型:silverstripe-module

0.4.0 2019-08-14 03:19 UTC

This package is auto-updated.

Last update: 2024-09-29 05:01:11 UTC


README

Build Status

从SilverStripe以各种形式导入和导出数据,包括CSV。此模块作为框架中发现的BulkLoader功能的替代/彻底翻新。

加载过程

  1. 从源(BulkLoaderSource)检索原始数据。
  2. 数据以可迭代的行(每行是标题-值映射的数组)提供。
  3. 根据用户/开发者提供的映射将行映射到标准格式。
  4. 将数据设置/链接/转换到占位符DataObject。
  5. 现有记录替换占位符,或占位符成为全新的DataObject。
  6. DataObject经过验证并保存。
  7. 所有结果都存储在BulkLoader_Result中。

用户定义的列映射

用户可以选择哪些列映射到DataObject字段。这消除了定义标题或标题的任何需求。用户可以声明数据的第一行实际上是标题行。映射将在下次在同一个GridField上导入时保存。

gridfieldimporter

Grid Field Importer

这是一个网格字段组件,用户可以选择CSV文件并将其列映射到数据字段。

$importer = new GridFieldImporter('before');
$gridConfig->addComponent($importer);

导入器使用了CSVFieldMapper,它显示了CSV的开始内容。

BulkLoaderSource

BulkLoaderSource提供迭代器以获取记录数据。数据可以来自任何地方,如CSV文件、Web API等。

它可以独立于BulkLoader使用来获取数据。

$source = new CsvBulkLoaderSource();
$source->setFilePath("files/myfile.csv")
    ->setHasHeader(true)
    ->setFieldDelimiter(",")
    ->setFieldEnclosure("'");

foreach($source->getIterator() as $record){
    //do stuff
}

(更好的)BulkLoader

  • 从特定来源保存数据并将其通过ORM持久化到数据库。
  • 确定可以映射到的字段,可以是根据模型编写的、由配置提供的,或两者兼而有之。
  • 检测现有记录,并基于标准跳过或更新它们。
  • 根据给定的映射将源数据映射到新的/现有的DataObjects。
  • 找到、创建并将关系对象连接到对象。
  • 可以在处理之前清除所有记录。
$source = new CsvBulkLoaderSource();
$source->setFilePath("files/myfile.csv");

$loader = new BetterBulkLoader("Product");
$loader->setSource($source);
$loader->addNewRecords = false;  // an option to skip new records

$result = $loader->load();

ListBulkLoader

通常您会希望将批量加载限制在特定的DataList中。ListBulkLoader是BulkLoader的一种变体,它可以从给定的DataList中添加和删除记录。当然,DataList本身没有实现add方法,所以您可能发现它对HasManyList更有用。

$category = ProductCategory::get()->first();

$source = new CsvBulkLoaderSource();
$source->setFilePath("productlist.csv");

$loader = new ListBulkLoader($category->Products());
$loader->setSource($source);

$result = $loader->load();

将记录数据映射到标准格式

您可以提供columnMap将传入的记录映射到标准格式。

$loader->columnMap = array(
    'first name' => 'FirstName',
    'Name' => 'FirstName',
    'bio' => 'Biography',
    'bday' => 'Birthday',
    'teamtitle' => 'Team.Title',
    'teamsize' => 'Team.TeamSize',
    'salary' => 'Contract.Amount'
);

此列映射由GridFieldImporter组件内的CSVFieldMapper控件生成。

脚手架与定义可映射字段

如果您没有自己定义它们,则可映射字段将进行脚手架设置。这包括关系上的字段,以便关系可以连接起来。

很可能会有您不想映射的字段,在这种情况下,您应该在您的加载器上指定一个mappableFields数组。

$loader->mappableFields = array(
    'FirstName' => 'First Name',
    'Surname' => 'Last Name',
    'Biography' => 'Biography',
    'Birthday' => 'Birthday',
    'Team.Title' => 'Team'
);

转换传入的记录数据

您可能想要对传入的记录数据进行一些转换。这可以通过指定一个针对记录字段名称的回调来完成。

$loader->transforms = array(
    'Code' => array(
        'callback' => function($value, $placeholder) {
            //capitalize course codes
            return strtoupper($value);
        }
    )
);

要求特定的数据存在

没有所需数据的传入记录将被跳过。

$loader->transforms = array(
    'Title' => array(
        'required' => true
    )
);

请注意,默认情况下会跳过空记录。

创建和链接相关DataObjects

批量加载器可以通过提供回调或使用Relation.FieldName样式的“点符号”来处理链接和创建has_one关系对象。

您可以在BulkLoader级别指定是否创建和关联记录,然后您可以指定每个字段的操作行为。默认行为是同时关联和创建关系对象。

以下是配置示例:

$loader->transforms = array(
    //link and create courses
    'Course.Title' = array(
        'link' => true,
        'create' => true
    ),
    //only link to existing tutors
    'Tutor.Name' => array(
        'link' => true,
        'create' => false
    ),
    //custom way to find parent courses
    'Parent' => array(
        'callback' => function($value, $placeholder) use ($self){
            return Course::get()
                ->filter("Title", $value)
                ->first();
        }
    )
);

注意,在上面的示例中,$placeholder指的是一个占位符DataObject,用于填充以便保存,或用于检查重复项。您不应在回调中调用$placeholder->write()

指定关系列表

与您可能使用ListBulkLoader将记录限制在给定的DataList中一样,您也可能希望将关系记录限制在列表中。

$loader->transforms = array(
    //link and create courses
    'Course.Title' = array(
        'list' => $self->Courses()
    )
);

确定何时覆盖现有的(重复的)DataObject

对记录数据执行重复检查,映射到标准化的形式。

您可以对数据字段执行重复检查

//course is a duplicate when title is the same
$loader->duplicateChecks = array(
    "Title"
);

或在关系上执行

//course selection is a duplicate when course is the same
$loader->duplicateChecks = array(
    "Course.Title"
);

您还可以使用回调函数查找重复项

$loader->duplicateChecks = array(
    "FooBar" => array(
        "callback" => function($fieldName, $record) {
            if(!isset($record["FirstName"]) || !isset($record["LastName"])){
                return null;
            }

            return Person::get()
                ->filter("FirstName", $record['FirstName'])
                ->filter("LastName", $record['LastName'])
                ->first();
        }
    )
);

在导入期间发布页面

如果您正在导入SiteTree实例,可以使用此配置自动发布这些页面

$loader->setPublishPages(true);

替换所有“旧版”ModelAdmin导入器

一些简单的yaml配置选项,帮助替换所有导入功能。

ModelAdmin:
    removelegacyimporters: true
    addbetterimporters: true

仅删除(非自定义)的scaffolded导入器

ModelAdmin:
    removelegacyimporters: scaffolded

故障排除

缺少关系对象

如果在加载时编写关系对象,并且它们未通过验证,则加载器将简单地忽略该关系对象。

多个关系数据字段映射到同一关系

如果您将多个字段映射到同一关系,您可能会遇到错误地将现有关系对象连接到一起的情况。映射的第一个字段是用于查找关系的相同字段。例如,您可能希望使用标题来查找/创建关系,然后向该关系添加金额,而不是通过金额查找/创建关系,并设置标题。

使用mappableFields数组定义正确的顺序以修复此问题。

贡献

请尽您所能为此模块做出贡献。查看问题里程碑以了解需要完成的工作。

许可证

MIT

作者

Jeremy Shipman (http://jeremyshipman.com)