drupal 迁移_您的第一个Drupal 8迁移

drupal 迁移

Migrate is one of the most established modules in the Drupal ecosystem. So much so that with Drupal 8, a decision has been made to get some of its functionality ported and added to Drupal core. An important reason was that the traditional upgrade between major releases was replaced with a migration of Drupal 6 or 7 content and configuration to Drupal 8.

迁移是Drupal生态系统中最完善的模块之一。 如此之多,以至于对于Drupal 8,已经决定将其某些功能移植并添加到Drupal核心中。 一个重要的原因是,主要版本之间的传统升级已替换为将Drupal 6或7的内容和配置迁移到Drupal 8。

Drupal 8 logo

Not all the functionality of the Migrate module has been moved into core though. Rather, we have the basic framework within the core migrate module and the functionality serving the upgrade path from Drupal 6 and 7 within the core migrate_drupal module. What’s left can be found in a host of contrib modules. The most important is Migrate Tools which contains, among other things, drush commands and the UI for running migrations. Additionally, the Migrate Source CSV, Migrate Source XML and Migrate Source JSON modules provide plugins for the most used types of migration sources.

但是,并非迁移模块的所有功能都已移入核心。 相反,我们在核心migrate模块中拥有基本框架,并且在核心migrate_drupal模块中具有从Drupal 6和7升级路径的功能。 剩下的内容可以在许多contrib模块中找到。 最重要的是迁移工具 ,该工具除其他外还包括drush命令和用于运行迁移的UI。 此外, Migrate Source CSVMigrate Source XMLMigrate Source JSON模块提供了用于最常用类型的迁移源的插件。

In this article we are going to look at how migration works in Drupal 8 by migrating some content into node entities. For simplicity, the data we play with resides in tables in the same database as our Drupal installation. If you want to see the final code, you can check it out in this repository.

在本文中,我们将通过将某些内容迁移到节点实体中来研究迁移在Drupal 8中的工作方式。 为简单起见,我们使用的数据与Drupal安装位于同一数据库的表中。 如果您想查看最终代码,可以在此存储库中检出。

Drupal 8迁移理论 (Drupal 8 Migration Theory)

The structure of a migration in Drupal 8 is made up of three main parts: the source, the process and the destination, all three being built using the new Drupal 8 plugin system. These three parts form a pipeline. The source plugin represents the raw data we are migrating and is responsible for delivering individual rows of it. This data is passed to one or more process plugins that perform any needed manipulation on each row field. Finally, once the process plugins finish preparing the data, the destination plugins save it into Drupal entities (either content or configuration).

Drupal 8中的迁移结构由三个主要部分组成:源,流程和目标,所有这三个部分都是使用新的Drupal 8插件系统构建的 。 这三个部分构成一条管道。 源插件表示我们正在迁移的原始数据,并负责传递其中的各个行。 此数据将传递到一个或多个进程插件,这些插件在每个行字段上执行任何所需的操作。 最后,一旦流程插件完成了数据准备,目标插件便将其保存到Drupal实体(内容或配置)中。

Creating a migration involves using such plugins (by either extending or directly using core classes). All of these are then brought together into a special migration configuration entity. This is shipped as module config that gets imported when the module is first enabled or can be constructed using a template (a case we won’t be exploring today). The migration configuration entity provides references to the main plugins used + additional metadata about the migration.

创建迁移涉及使用此类插件(通过扩展或直接使用核心类)。 然后将所有这些都放到一个特殊的迁移配置实体中。 这是作为模块配置提供的,该模块配置在首次启用时被导入,或者可以使用模板进行构建 (这种情况我们今天将不再探讨)。 迁移配置实体提供对使用的主要插件的引用以及有关迁移的其他元数据。

电影迁移 (Movie Migration)

Let us now get down to it and write a couple of migrations. Our data model is the following: we have two tables in our database: movies and movies_genres. The former has an ID, name and description while the latter has an ID, name and movie ID that maps to a movie from the first table. For the sake of simplicity, this mapping is one on one to avoid the complication of a third table. Here is the MySQL script that you can use to create these tables and populate with a few test records (if you want to follow along):

现在让我们开始讨论并编写一些迁移。 我们的数据模型如下:我们已经在我们的数据库中有两个表: moviesmovies_genres 。 前者具有ID,名称和描述,而后者具有ID,名称和电影ID,它们映射到第一个表中的电影。 为了简单起见,此映射是一对一的,以避免第三张表的复杂化。 这是MySQL脚本,可用于创建这些表并填充一些测试记录(如果您想遵循的话):

CREATE TABLE `movies` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `description` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

CREATE TABLE `movies_genres` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `movie_id` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

INSERT INTO `movies` (`id`, `name`, `description`)
VALUES
	(1, 'Big Lebowsky', 'My favorite movie, hands down.'),
	(2, 'Pulp fiction', 'Or this is my favorite movie?');

INSERT INTO `movies_genres` (`id`, `movie_id`, `name`)
VALUES
	(1, 1, 'Comedy'),
	(2, 1, 'Noir'),
	(3, 2, 'Crime');

What we want to achieve is migrate the movies into basic Drupal Article nodes and the genres into taxonomy terms of the Tags vocabulary (which the Article nodes reference via a field). Naturally, we also want the migration to mirror the association between the movies and the genres.

我们想要实现的是将电影迁移到基本的Drupal Article节点,并将流派迁移到Tag词汇的分类术语(Article节点通过字段引用)。 当然,我们也希望迁移能够反映电影和流派之间的关联。

体裁 (Genres)

Let us first take care of the genre migration because in Drupal, the movies will depend on them (they will reference them).

首先让我们关注流派的迁移,因为在Drupal中,电影将依赖于它们(它们将引用它们)。

Inside the config/install folder of our module, we need the following configuration entity file called migrate.migration.genres.yml:

在我们模块的config/install文件夹中,我们需要以下配置实体文件,名为migrate.migration.genres.yml

id: genres
label: Genres
migration_group: demo
source:
  plugin: genres
  key: default
destination:
  plugin: entity:taxonomy_term
process:
  vid:
    plugin: default_value
    default_value: tags
  name: name

The first three elements of this configuration are the migration ID, label and group it belongs to. The following three keys are responsible for the three main parts of the migration pipeline mentioned earlier. Let’s talk about the latter three separately.

此配置的前三个元素是它所属的迁移ID,标签和组。 以下三个键负责前面提到的迁移管道的三个主要部分。 让我们分别讨论后三个。

资源 (Source)

Under the source key we specify which plugin the migration should use to represent and deliver the source data (in our case the plugin with the ID of genres). The key key is used to specify which database should our source query use (that is where our data is).

在source键下,我们指定迁移应使用哪个插件来表示和传递源数据(在我们的示例中,ID为genres的插件)。 key键用于指定源查询应使用哪个数据库(即我们的数据所在的位置)。

So in the Plugin/migrate/source folder of our module, let’s create our SQL based source plugin for our genres:

因此,在模块的Plugin/migrate/source文件夹中,让我们为体裁创建基于SQL的源插件:

Genres.php

Genres.php

namespace Drupal\demo\Plugin\migrate\source;

use Drupal\migrate\Plugin\migrate\source\SqlBase;

/**
 * Source plugin for the genres.
 *
 * @MigrateSource(
 *   id = "genres"
 * )
 */
class Genres extends SqlBase {

  /**
   * {@inheritdoc}
   */
  public function query() {
    $query = $this->select('movies_genres', 'g')
      ->fields('g', ['id', 'movie_id', 'name']);
    return $query;
  }

  /**
   * {@inheritdoc}
   */
  public function fields() {
    $fields = [
      'id' => $this->t('Genre ID'),
      'movie_id' => $this->t('Movie ID'),
      'name' => $this->t('Genre name'),
    ];

    return $fields;
  }

  /**
   * {@inheritdoc}
   */
  public function getIds() {
    return [
      'id' => [
        'type' => 'integer',
        'alias' => 'g',
      ],
    ];
  }
}

Since we are using a SQL source, we need to have our own source plugin class to provide some information as to how the data needs to be read. It’s not enough to use an existing one from core. The query() method creates the query for the genre data, the fields() method defines each individual row field and the getIds() method specifies the source row field that acts as the unique ID. Nothing complicated happening here.

由于我们使用的是SQL源代码,因此我们需要有自己的源代码插件类来提供一些有关如何读取数据的信息。 仅使用核心中的现有内核是不够的。 query()方法创建对体裁数据的查询, fields()方法定义每个单独的行字段,而getIds()方法指定充当唯一ID的源行字段。 这里没有什么复杂的事情。

We are extending from SqlBase which, among other things, looks for the plugin configuration element named key to learn which database it should run the query on. In our case, the default one, as we detailed in the migration configuration entity.

我们从SqlBase进行扩展,该数据库除其他外还查找名为key的插件配置元素,以了解应在哪个数据库上运行查询。 在我们的例子中,默认值是默认值,正如我们在迁移配置实体中详细介绍的那样。

And this is all we need for our simple source plugin.

这就是我们简单的源代码插件所需要的。

目的地 (Destination)

For the migration destination, we use the default core taxonomy term destination plugin which handles everything for us. No need to specify anything more.

对于迁移目标,我们使用默认的核心分类法术语“目标”插件,该插件可为我们处理所有事情。 无需指定其他任何内容。

处理 (Process)

Under the process key of the migration, we list each destination field we want populated and one or more process plugins that transform the source row fields into data for the destination fields. Since we want the genres to be all terms of the Tags vocabulary, for the vid field we use the default_value plugin which accepts a default_value key that indicates the value each record will have. Since all will be in the same vocabulary, this works well for us.

在迁移的process键下,我们列出了要填充的每个目标字段,以及一个或多个将源行字段转换为目标字段数据的流程插件。 由于我们希望流派是“标记”词汇表的所有术语,因此对于vid字段,我们使用default_value插件,该插件接受default_value键,该键指示每个记录将具有的值。 由于所有人都将使用同一词汇表,因此这对我们来说很好。

Lastly, for the term name field we can simply specify the source row field name without an explicit plugin name. This will, under the hood, use the get plugin that simply takes the data from the source and copies it over unaltered to the destination.

最后,对于术语名称字段,我们可以简单地指定源行字段名称,而无需显式的插件名称。 这将在后台使用get插件,该插件简单地从源中获取数据并将其原封不动地复制到目的地。

For more information on how you can chain multiple process plugins in the pipeline or what other such plugins you have available from core, I recommend you check out the documentation.

有关如何在管道中链接多个流程插件或您可以从核心中获得哪些其他此类插件的更多信息,建议您查阅文档

电影 (Movies)

Now that our genres are importable, let’s take a look at the movies migration configuration that resides in the same folder as the previous (config/install):

现在我们的流派是可导入的,让我们看一下电影迁移配置,该迁移配置与上一个( config/install )位于同一文件夹中:

migrate.migration.movies.yml

migration.migration.movi​​es.yml

id: movies
label: Movies
migration_group: demo
source:
  plugin: movies
  key: default
destination:
  plugin: entity:node
process:
  type:
    plugin: default_value
    default_value: article
  title: name
  body: description
  field_tags:
    plugin: migration
    migration: genres
    source: genres
migration_dependencies:
  required:
    - genres

We notice the same metadata as before, the three main parts of the migration (source, process and destination) but also the explicit dependency which needs to be met before this migration can be successfully run.

我们注意到与以前相同的元数据,是迁移的三个主要部分(源,过程和目标),但是在成功运行此迁移之前,还需要满足显式依赖关系。

资源 (Source)

Like before, let’s take a look at the movies source plugin, located in the same place as the genres source plugin (Plugin/migrate/source ):

和以前一样,让我们​​看一下movies源插件,它与genres源插件位于同一位置( Plugin/migrate/source ):

Movies.php:

Movies.php

namespace Drupal\demo\Plugin\migrate\source;

use Drupal\migrate\Plugin\migrate\source\SqlBase;
use Drupal\migrate\Row;

/**
 * Source plugin for the movies.
 *
 * @MigrateSource(
 *   id = "movies"
 * )
 */
class Movies extends SqlBase {

  /**
   * {@inheritdoc}
   */
  public function query() {
    $query = $this->select('movies', 'd')
      ->fields('d', ['id', 'name', 'description']);
    return $query;
  }

  /**
   * {@inheritdoc}
   */
  public function fields() {
    $fields = [
      'id' => $this->t('Movie ID'),
      'name' => $this->t('Movie Name'),
      'description' => $this->t('Movie Description'),
      'genres' => $this->t('Movie Genres'),
    ];

    return $fields;
  }

  /**
   * {@inheritdoc}
   */
  public function getIds() {
    return [
      'id' => [
        'type' => 'integer',
        'alias' => 'd',
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function prepareRow(Row $row) {
    $genres = $this->select('movies_genres', 'g')
      ->fields('g', ['id'])
      ->condition('movie_id', $row->getSourceProperty('id'))
      ->execute()
      ->fetchCol();
    $row->setSourceProperty('genres', $genres);
    return parent::prepareRow($row);
  }
}

We have the same three required methods as before, that do the same thing: query for and define the data. However, here we also use the prepareRow() method in order to alter the row data and available fields. The purpose is to select the ID of the movie genre that matches the current row (movie). That value is populated into a new source field called genres, which we will see in a minute how it’s used to save the Tags taxonomy term reference.

我们具有与以前相同的三个必需方法,它们执行相同的操作:查询和定义数据。 但是,这里我们还使用prepareRow()方法来更改行数据和可用字段。 目的是选择与当前行(电影)匹配的电影流派的ID。 该值将填充到一个名为genres的新源字段中,我们将在稍后看到它如何用于保存“标签”分类标准术语参考。

目的地 (Destination)

In this case, we use the node entity destination plugin and we need nothing more.

在这种情况下,我们使用节点实体目标插件,我们仅需使用。

处理 (Process)

There are four fields on the Article node we want populated with movie data. First, for the node type we use the same technique as before for the taxonomy vocabulary and set article to be the default value. Second and third, for the title and body fields we map the movie name and description source fields unaltered.

我们希望用电影数据填充“文章”节点上的四个字段。 首先,节点type ,我们使用相同的技术和以前的分类词汇表和一组article为默认值。 第二和第三,对于标题和正文字段,我们将电影名称和描述源字段保持不变。

Lastly, for the tags field we use the migration process plugin that allows us to translate the ID of the genre (that we added earlier to the genres source row field) into the ID of its corresponding taxonomy term. This plugin does this for us by checking the migration mapping of the genres and reading these IDs. And this is why the genres migration is also marked as a dependency for the movies import.

最后,对于标签字段,我们使用迁移过程插件 ,该插件允许我们将流派的ID(我们之前在genres源行字段中添加的ID)转换为其相应的分类术语的ID。 该插件通过检查流派的迁移映射并读取这些ID为我们完成此任务。 这就是为什么流派迁移也被标记为电影导入的依赖项的原因。

激活和运行迁移 (Activating and Running the Migration)

Now that we have our two migration configuration entities and all the relevant plugins, it’s time to enable our module for the first time and have the configuration imported by Drupal. If your module was already enabled, uninstall it and then enable it again. This will make the config import happen.

现在我们有了两个迁移配置实体和所有相关的插件,是时候首次启用我们的模块并由Drupal导入配置了。 如果您的模块已经启用,请先将其卸载,然后再次启用它。 这将使配置导入发生。

Additionally, in order to run the migrations via Drush (which is the recommended way of doing it), install the Migrate Tools module. Then all that’s left to do is to use the commands to migrate or rollback the movies and genres.

此外,为了通过Drush运行迁移(建议这样做),请安装“ 迁移工具”模块。 然后,剩下要做的就是使用命令来迁移或回滚电影和流派。

To see the available migrations and their status:

要查看可用的迁移及其状态:

drush migrate-status

To import all migrations:

导入所有迁移:

drush migrate-import --all

To roll all migrations back:

要回滚所有迁移:

drush migrate-rollback --all

结论 (Conclusion)

And there we have it – a simple migration to illustrate how we can now import, track and roll back migrations in Drupal 8. We’ve seen how the plugin system is used to represent all these different components of functionality, and how the migration definition has been turned into configuration that brings these elements together.

我们已经有了它–一个简单的迁移来说明我们现在如何在Drupal 8中导入,跟踪和回滚迁移。我们已经了解了如何使用插件系统来表示所有这些功能的不同组件,以及如何定义迁移已转变为将这些元素整合在一起的配置。

There is much more to learn, though. You can use different source plugins, such as for data in CSV or JSON, complex process plugins (or write your own), or even custom destination plugins for whatever data structure you may have. Good luck!

但是,还有更多的东西要学习。 您可以使用不同的源插件,例如用于CSV或JSON中的数据,复杂的流程插件(或编写您自己的插件),甚至可以针对您可能拥有的任何数据结构使用自定义目标插件。 祝好运!

翻译自: https://www.sitepoint.com/your-first-drupal-8-migration/

drupal 迁移

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值