迁移:prepare()和prepareRow()有什么区别?


8

使用迁移模块:我了解prepareRow()在行上运行过滤器,并应根据某些条件返回TRUE或FALSE,这允许迁移或不迁移行,但是有人可以澄清一下:

  • 何时使用prepare()
  • 何时使用prepareRow()
  • 为什么不在初始sql查询中添加过滤器来过滤您可能会删除/包含在上述任一方法中的行结果

谢谢!


1
不通过sql查询进行过滤的原因之一是为您决定要跳过的行添加映射。例如,我正在将用户导入现有站点。我想跳过目标上已经存在的用户,并且想添加一个映射,就好像该用户实际上是导入的一样,因此其他依赖于此的迁移也可以顺利进行。
jonhattan

Answers:


9

该项目提供的Migrations类文档中对此进行了详细介绍。特别是在“ 仅实现通用迁移方法”页面中,该页面显示以下内容,并包括更多简单的示例函数实现。从文档...

函数prepare_row($ row)

加载数据行后,源类的next()方法调用prepareRow()方法。$ row参数是一个stdClass对象,其中包含源提供的原始数据。实现prepareRow()的主要原因有两个:

  1. 在数据行通过任何其他方法和处理程序之前对其进行修改:例如,获取相关数据,拆分源字段,基于某种逻辑组合或创建新的源字段。
  2. 要有条件地跳过一行(返回FALSE)。

函数prepare($ entity,stdClass $ row)

在迁移类的prepare()方法已调用所有字段级prepare()方法之后,并且紧接在保存目标对象之前,它由目标类prepare()方法调用。$ entity参数是目标对象,由初始字段映射填充并由字段级方法操纵;$ row参数是一个对象,其中包含prepareRow()和所有回调已应用之后的数据。prepare()方法是在将目标对象保存到Drupal数据库之前对其进行操作的最后机会。重要的是要记住,由于它是在字段处理程序之后调用的,所以字段将采用其完全展开的形式(即,在Drupal 7中,文本字段的值将为 $entity->field_textual_data['und'][0]['value']而不是简单的 $entity->field_textual_data)

所述迁移模块是一个框架,它允许用户从一个源数据块的到目的地位置和配置包封迁移过程。迁移包括:

  • 定义数据在哪里
  • 定义数据应该去哪里
  • 提取一条数据(行)
  • 清理数据
  • 开始移动数据(例如移入实体)
  • 实际移动数据
  • 移动数据后,执行其他操作

API提供了挂钩,以影响在此迁移的生命周期中要移动的数据。通过通过初始查询从迁移中排除数据,您可以限制对可移动总数据的控制权。对于子迁移,您可能会发现这很有用。但是在一般的内容迁移中,您希望迁移尽可能地全面。


谢谢tenken,正是我想要的东西。还要理解从初始查询中删除元素的想法。
user4984 2014年

6

如果可以通过在查询中写入来选择正确的行,则可以选择preprareRow(),但是可以在更复杂的系统中使用该系统,在迁移行之前可能需要几个参数。在这种情况下,遍历所有行并逐行执行逻辑会更容易。

prepare()在prepareRow()之后运行,这是在将实体保存到数据库之前更改实体的最后机会。

有关此的更多信息,请参见:https : //www.drupal.org/node/1132582


我发现这是简洁明了的
Johnathan Elmore 2014年

3

这是部分答案,绝不是完整的答案。我也渴望找到更多关于这两个方面的信息。因此,这可能是讨论的一部分;尽管由于以下代码段以及如何使用上述类的示例,所以我将其作为答案而不是评论来编写。

让我举例说明我的一些使用prepareRow()的用法,正如它所说的那样。

最近,我正在提供一些要从非Drupal数据库导入的数据。我要添加的实体要求输入我在数据导入中没有的字段。

因此,在创建源类之前,我可以添加

  $source_fields = array(
    'changed' => t('Timestamp of when the change was made.'),
    'created' => t('Timestamp of when the node was Created.'),
 );

然后在函数prepareRow中,我可以执行以下操作

$nowtimestamp = mktime(date('Y-m-d'));
$row->changed = $nowtimestamp;
$row->created = $nowtimestamp;

您也可以在必要时在此处运行php if / else语句。

我还在代码中使用了prepare函数,并正在使用它为实体分配值。

$account->field_job_location [und][0]['tid'] = $row->job_location_tid;

在制作自己的自定义节点插件时,只需要在这种情况下使用它即可。

另外,如果您需要对此进行计算,则可以在prepare()之前运行的prepareRow中进行操作

例如,在导入中,我有一个标记为“镇”的值-可以将其转换为术语ID。

 if ($TownCity == 'London' ){
            $row->job_location_tid = '10';
      } else {
        $row->job_location_tid = '11';
      } 

我希望这有帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.