kalio/ezmigrationbundle

Kaliop eZ-Migration Bundle

资助包维护!
tanoconsulting

安装次数: 349,644

依赖: 9

建议者: 0

安全: 0

星标: 53

关注者: 8

分支: 81

开放问题: 23

类型:symfony-bundle

6.3.4 2023-06-16 08:47 UTC

README

此包使得对eZPlatform 1和2 / eZPublish 5数据库结构和内容的更改易于编程部署。

它受到DoctrineMigrationsBundle的启发。

您可以将其视为旧版ezxmlinstaller扩展的孙子。

要求

  • PHP 5.6或更高版本。

  • eZPlatform 1, eZPlatform 2或eZPublish Enterprise 5.4或eZPublish Community 2014.11或更高版本。

注意:对于eZPlatform 3(即Ibexa DXP),请前往tanoconsulting/ezmigrationbundle2。对于Ibexa DXP 4,请访问tanoconsulting/ibexa-migration-bundle

安装

在composer.json文件中bundle列表的末尾,无论是require还是require-dev,添加

"kaliop/ezmigrationbundle": "^6.0"

保存并运行

composer update --dev kaliop/ezmigrationbundle

这将安装包及其所有依赖项。

请确保您已在kernel中注册了该包。检查app/appKernel.php(对于eZPublish ezpublish/EzPublishKernel.php

方法registerBundles应类似于

public function registerBundles()
{
    $bundles = array(
        ... more stuff here ...
        new \Kaliop\eZMigrationBundle\EzMigrationBundle()
    );
}

检查包是否正确安装

如果您运行php bin/console(对于eZPublish php ezpublish/console),您应该看到以下新命令在列表中

kaliop
  kaliop:migration:generate
  kaliop:migration:mass_migrate
  kaliop:migration:migrate
  kaliop:migration:migration
  kaliop:migration:resume
  kaliop:migration:status

这表明该包已正确安装并注册。

注意:命令kaliop:migration:update保留用于兼容性,将在未来的版本中删除。

更新包

要获取最新版本,您可以使用composer更新包到最新可用版本

composer update kaliop/ezmigrationbundle

有关从一个主要版本升级到下一个版本的说明,请参阅此readme的底部。

入门

所有命令都接受标准的Symfony/eZPublish 5选项,尽管其中一些可能对命令的执行没有影响。

生成一个新的空迁移定义文件

此包提供了一种命令,可以轻松生成一个新的空白迁移定义文件,存储在特定的包中。

例如

php bin/console kaliop:migration:generate --format=yml MyProjectBundle

上述命令将在MyProjectBundle包的MigrationVersions目录中放置一个新yml骨架文件。

如果该目录不存在,则该命令将为您创建它,只要包存在且已注册即可。如果命令成功执行,它将创建一个新yml文件,其命名模式如下:YYYYMMDDHHMMSS_placeholder.yml。我们鼓励您重命名文件并将placeholder部分更改为更有意义的内容,但请保留时间戳部分和下划线,以及扩展名。

(骨架Yaml文件的内部内容存储为twig模板)

列出所有迁移及其状态

要查看系统中所有可用的迁移定义以及它们是否已应用,只需在eZPublish 5根目录中运行状态命令即可

php bin/console kaliop:migration:status

已应用的迁移列表存储在数据库中,名称为kaliop_migrations的表中。如果需要使用该表的不同名称,可以更改Symfony参数ez_migration_bundle.table_name。如果需要,该包会自动创建该表。

应用迁移

要应用所有可用的迁移,请在您的 eZPublish 5 根目录中运行 migrate 命令。

 php bin/console kaliop:migration:migrate

注意:如果您刚刚执行了上述命令并收到错误信息,因为您刚刚生成的迁移定义文件无效,请不要担心——这是按设计进行的。直接跳到下一段...

注意:迁移默认以管理员用户 ID 14 执行。如果没有这个数据库中的用户账户,您必须通过传递 -a 标志来指定使用另一个管理员账户。

应用单个迁移文件

要应用单个迁移,请运行 migrate 命令并传入其定义的路径,如下所示

php bin/console kaliop:migration:migrate --path=src/MyNamespace/MyBundle/MigrationVersions/20160803193400_a_migration.yml

注意:您还可以使用 --path 标志指定一个文件夹,在这种情况下,将执行该文件夹中包含的所有迁移定义。

编辑迁移文件

到目前为止一切顺利,但是实际上可以使用迁移执行哪些操作呢?

每个迁移定义由一系列步骤组成,其中每个步骤定义一个操作。

创建“文件夹”内容的迁移的一个简单示例

-
    mode: create
    type: content
    content_type: folder
    parent_location: 2
    attributes:
        name: hello world

在 Yaml 迁移中,您可以执行以下类型的操作

  • 内容的创建、更新和删除
  • 内容类型的创建、更新和删除
  • 内容组的创建、更新和删除
  • 内容版本的删除
  • 语言的创建和删除
  • 位置的创建、更新和删除
  • 对象状态的创建、更新和删除
  • 对象状态组的创建、更新和删除
  • 角色的创建、更新和删除
  • 部分的创建、更新和删除
  • 标签的创建和删除(来自 Netgen Tags Bundle)
  • URL别名和通配符的创建和删除
  • 用户的创建、更新和删除
  • 用户组的创建、更新和删除
  • 从垃圾桶中清除和恢复内容
  • 文件的创建、追加、复制、重命名和删除
  • 执行 SQL 查询
  • 执行命令行脚本
  • 执行 Symfony 服务的 方法
  • 执行 php 函数和静态方法
  • 执行HTTP调用
  • 发送电子邮件
  • 遍历数组并对每个元素执行上述操作之一
  • 取消、挂起或暂停迁移本身
  • 生成并保存新的迁移定义

所有支持的迁移语言特性的更多详细信息请参阅DSL语言描述

自定义迁移

对于更具体的需求,您还可以使用其他两种类型的迁移

  • SQL迁移
  • PHP迁移

SQL迁移

生成SQL迁移定义的示例命令

 php bin/console kaliop:migration:generate MyBundle create-new-table --format=sql

这将创建以下文件,您可以自由编辑

.../MyBundle/Migrations/2016XXYYHHMMSS_mysql_create-new-table.sql

注意 如果您重命名sql文件,请注意,该文件名中第一个和第二个下划线字符之间的部分是它应该应用的数据库类型。如果您后来尝试在运行PostgreSQL的eZPublish安装上执行该迁移,迁移将失败。当然,您可以创建特定数据库类型的特定SQL迁移。

迁移包本身不对支持的数据库类型施加限制,但它基于Doctrine DBAL,因此它只能在Doctrine支持的数据库上工作。

注意 您还可以将要执行的SQL语句保存到以yml格式编写的迁移文件中。这为您提供了更多选项,例如设置和解析引用。Yml格式的迁移文件不需要在名称中包含db类型。

注意 如果迁移中的SQL语句(或语句)太长,迁移可能会失败或只部分应用,在某些情况下(例如使用MySQL)甚至不报告错误。如果您需要执行多个长查询,您最好将它们拆分,要么在多个.sql迁移中,要么在一个.sql步骤的单一.yml迁移中。

PHP迁移

如果您需要进行的操作类型对于YML或SQL来说太复杂,您可以使用PHP类作为迁移定义。要生成PHP迁移定义,请执行

 php bin/console kaliop:migration:generate MyBundle AMigrationClass --format=php

这将创建以下文件,您可以自由编辑

.../MyBundle/Migrations/2016XXYYHHMMSS_AMigrationClass.php

如您在生成的定义中看到的那样,用于迁移的PHP类需要实现特定的接口。Symfony DIC容器传递给迁移类,以便它可以访问它所需的所有服务、参数和其他内容。

有关使用PHP完成的迁移定义的更详细示例,请参阅此包的MigrationVersions文件夹。

注意 如果您重命名php文件,请注意,文件名和它包含的类名称是关联的 - 应用程序的标准自动加载机制在加载迁移定义时不适用。这也是为什么用作迁移的PHP类不应使用命名空间的原因。

注意 还可以通过在yaml迁移中声明它为迁移步骤来运行任何现有Symfony服务的任何方法。有关详细信息,请参阅相关DSL

注意 也可以通过在yaml迁移中将其声明为迁移步骤来运行任何现有的php函数或静态类方法。有关详细信息,请参阅相关DSL

重新执行失败的迁移

重新执行“失败”状态的迁移的最简单方法是将其从迁移表中删除

php bin/console kaliop:migration:migration migration_name --delete

从迁移表中删除迁移信息后,运行migrate命令将再次执行它。

事务/回滚更改的使用

默认情况下,该bundle在每个迁移中都运行数据库事务。这意味着如果某个步骤失败,所有之前的步骤都会回滚,数据库将保持原始状态。这是设计内置的安全功能;

  • 如果您希望迁移步骤在单独的事务中执行,最简单的方法是为每个步骤创建一个单独的迁移文件
  • 您可以使用命令行标志-u来禁用migrate命令的事务使用

请注意,默认情况下,migrate命令在遇到第一个失败的迁移时停止,但可以使用标志执行它,允许它在出现故障的情况下继续执行所有可用的迁移。

至于回滚更改:由于eZPublish API的性质,对内容的更改回滚并不容易。因此,该bundle不提供内置的将数据库回滚到应用给定迁移之前版本的数据库支持。我们建议在应用迁移之前始终进行数据库快照,并在需要回滚更改时使用它。另一种方法是在迁移中编写一个单独的迁移来撤销更改。

通过事件监听器自定义迁移逻辑

将自定义逻辑连接到迁移执行的一个简单方法 - 而不必实现自己的定制操作执行器 - 是使用事件监听器。

在执行迁移时,为每个步骤触发两个事件

* ez_migration.before_execution => listeners receive a BeforeStepExecutionEvent event instance
* ez_migration.step_executed => listeners receive a StepExecutedEvent event instance

只有当迁移失败且某个步骤抛出特定的迁移中止异常时,才会触发事件

* ez_migration.migration_aborted => listeners receive a MigrationAbortedEvent event instance

当使用kaliop:migration:generate命令生成迁移时,将触发事件,允许修改将序列化为迁移步骤的数据

* ez_migration.migration_generated => listeners receive a MigrationGeneratedEvent event instance

要处理这些事件,您需要声明带标签的服务,例如:

my.step_executed_listener:
    class: my\helper\StepExecutedListener
    tags:
        - { name: kernel.event_listener, event: ez_migration.step_executed, method: onStepExecuted }

以及相应的php类

use Kaliop\eZMigrationBundle\API\Event\StepExecutedEvent;

class StepExecutedListener
{
    public function onStepExecuted(StepExecutedEvent $event)
    {
        // do something...
    }
}

Event Subscribers支持作为Event Listeners的替代方案,这是与Symfony项目标准一致的做法。

已知问题和限制

  • 与Doctrine Migrations Bundle不同,此bundle不支持更改回滚。请参阅上面的原因。

  • 如果您使用Doctrine Migrations Bundle来管理您的模式,您将得到处理属于Kaliop Migrations Bundle的数据库表的意外SQL创建。目前,最好的解决方案是在运行doctrine:migrations:diff和类似命令时使用命令行上的filter-expression参数,其值为kaliop_migrations_*

  • 如果在运行迁移时遇到致命错误,提示找不到节点或对象,这很可能与eZPublish中双内核的工作方式有关,以及传统内核和Symfony内核使用数据库的单独连接。由于迁移包默认将迁移的所有数据库更改封装在数据库事务中,当触发插槽允许传统内核清除其缓存时,传统内核无法看到Symfony内核应用到的数据库更改,并且根据使用的具体插槽,可能会因为致命错误而失败。最简单的解决方案是禁用事务的使用,通过向migrate命令传递-u标志。

  • 当您使用Solr搜索引擎包时,可能会出现类似的症状。在这种情况下,问题变得更加复杂,即使节点或对象在数据库事务中发送到Solr,Solr搜索索引可能也被配置为仅在短时间内延迟提交接收到的数据。一个已知的解决方案涉及

    • 将迁移步骤分离成独立的迁移
    • 通过使用migrate命令的-p标志,在每个事务(和进程)中运行迁移
    • 在迁移2 .. N中添加sleep迁移步骤
    • 以及/或者配置Solr始终立即提交更改到索引(例如,禁用commitwithin
  • 当在多核配置中使用SOLR并遇到java.lang.NegativeArraySizeException错误时,您必须将参数ez_migration_bundle.query_limit的默认值2147483647设置得更低

  • 如果在运行涉及大量内容更改的迁移时遇到没有错误消息的致命错误,例如更改具有许多内容的contentType,那么您可能正在耗尽php进程的内存。已知的解决方案包括

    • 通过运行带有选项'-d memory_limit=-1'的脚本,增加php脚本允许的最大内存量
    • 使用具有减少日志记录和禁用内核调试的Symfony环境执行迁移命令:默认的dev环境配置已知会泄漏内存
    • 尽可能将迁移转换成一次加载和逐个修改内容并在循环中修改的迁移。请参阅使用循环的示例这里
  • 如果遇到带有消息“您无法创建一个无效范围(“request”)的服务(“request”)”的致命错误,请查看以下问题以获取可能的解释和解决方案:https://jira.ez.no/browse/EZP-24691

  • 如果您使用的是2015.9之前的eZPublish版本,您将无法创建/更新包含对自定义模块/函数限制策略的角色定义。已知的解决方案是接管RoleService并修改其构造函数以将其注入所需限制

  • 在更新角色时,您必须在迁移中指定其所有策略。任何不在yml文件中的现有策略都将被删除。要轻松创建更新角色的迁移,请使用带有--type=role标志的migration:generate命令

  • 在创建内容类型时要小心:迁移包内部使用的eZPublish API允许您在内容类型标识符中使用破折号,即使生成的内容类型可能无法使用,例如。

    无效定义的示例

          type: ezstring
          name: Topbar-hover-color
          identifier: topbar-hover-color
    
  • 当eZ以集群模式设置时,如果您正在设置对ezimage、ezbinaryfile或ezmedia类型内容字段路径的引用,或者正在生成用于创建/更新它的迁移,您获得的路径值不是磁盘上的绝对路径,而是相对于'nfsvar'目录的路径,这使得它不适合直接用于内容创建/更新迁移等。请参阅Cookbook中的示例了解如何处理这种情况。

常见问题

如何在dev、test和prod环境中更新具有不同ID的特定内容?

A: 使用'reference/set'迁移步骤定义所需内容ID的引用,并使用Symfony参数为每个Symfony环境存储不同的值。例如

-
    type: reference
    mode: set
    identifier: content_id_ref
    value: '%a.parameter.name%'

-
    type: content
    mode: update
    match:
        content_id: "reference:content_id_ref"
    etc: ...

请注意,针对此问题还有许多其他解决方案,例如确保您的目标内容和位置在所有环境中都具有相同的Remote_id,或者将引用的值作为选项传递给migrate命令行。

如何更新现有角色以更改其策略?

当使用迁移更新角色时,您必须定义其所有策略。未定义的策略将被删除。确保您不会忘记任何现有策略的最安全且最简单的方法是首先生成一个更新迁移,其中包含角色当前定义的完整规范,然后手动编辑。

创建此类迁移的示例命令

php bin/console kaliop:migration:generate --type=role --mode=update --match-type=identifier --match-value=Anonymous bundleName

当通过generate命令将内容导出到yml迁移时,属性列表为空

A: 这很可能是由于使用不良的语言配置

是否有实现需要复杂迁移的常见任务的示例?

A: 是的,请参阅文件夹Resources/doc/Cookbook/

我可以在迁移中将外部工具(命令行脚本)作为一部分运行吗?

A: 当然。请参阅相关的dslcookbook示例以获取详细信息。

扩展包

支持自定义迁移

该包已被设计为可以轻松扩展,例如

  • 添加对自定义/复杂字段类型的支持
  • 添加对Yml定义中完全新动作的支持
  • 添加对存储迁移定义的新文件格式的支持
  • 添加对迁移定义中自定义引用的新解析器的支持
  • 接管迁移定义从文件系统加载或存储到数据库的方式
  • 等等...

遵循Symfony最佳实践,对于上述列表中的前4个选项,您需要做的只是创建一个服务并给它一个适当的标签(当然,实现该服务的类应该实现一个适当的接口)。

要找出您需要实现的标签名称,以及您可以覆盖的所有其他服务,请参阅services.yml文件

还可以定义自定义事件监听器/订阅者以扩展迁移执行逻辑。请参阅上面的专用段落以获取更多详细信息。

运行测试

该包使用PHPUnit运行功能测试。

在工作的eZPublish / eZPlatform安装中运行测试

要运行测试

export KERNEL_DIR=app (or 'ezpublish' for ezpublish 5.4/cp setups)
export SYMFONY_ENV=behat (or whatever your environment is)

bin/phpunit --stderr -c vendor/kaliop/ezmigrationbundle/phpunit.xml.dist

注意 测试不模拟与数据库的交互,但在其中创建/修改/删除许多类型的数据。因此,运行测试可能会留下陈旧/损坏的数据。建议使用专用的eZPublish安装或至少专用的数据库来运行测试套件。

为该包设置专用的测试环境

运行套餐测试的一个更安全的选择是设置一个专用环境,类似于在GitHub Actions上运行测试套件时使用的那种环境。优势是多方面的:一方面,你可以从任何你想要的eZPublish版本开始;另一方面,你将更有信心,你添加或修改的任何测试也将通过GitHub。缺点是你需要Docker和Docker-compose,而且你将使用的环境将与标准的eZPublish设置大相径庭!此外,构建这个环境将需要相当多的磁盘空间和时间。

设置专用测试环境并在其中运行测试的步骤

git clone --depth 1 https://github.com/tanoconsulting/euts.git teststack
# if you have a github auth token, it is a good idea to copy it now to teststack/docker/data/.composer/auth.json

# this config sets up a test environment with eZPlatform 2.5 running on php 7.4 / ubuntu jammy
export TESTSTACK_CONFIG_FILE=Tests/environment/.euts.2.5.env

./teststack/teststack build
./teststack/teststack runtests
./teststack/teststack stop

您还可以运行单个测试用例

./teststack/teststack runtests ./Tests/phpunit/01_CollectionsTest.php

注意:第一次运行时这将需要一些时间,但后续运行会更快。注意:请确保有足够的磁盘空间。

如果您想手动运行命令,例如symfony控制台

./teststack/teststack console cache:clear

或者轻松地访问数据库shell提示

./teststack/teststack dbconsole

或者命令行shell提示到运行测试的Docker容器

./teststack/teststack shell

在Docker容器中运行的测试使用文件Tests/environment/.euts.2.5.env中指定的debian/php/eZPlatform内核版本,如环境变量TESTSTACK_CONFIG_FILE中指定。如果没有设置该环境变量的值,则查找名为.euts.env的文件。如果不存在此类文件,则使用一些默认值,您可以在./teststack/README.md中的文档中找到它们。如果您想针对不同的eZ/php/mysql/debian版本进行测试,请

  • 创建.euts.env文件(如果尚不存在)
  • 向其中添加任何所需变量(请参考文件teststack/.euts.env.example作为指导)
  • 重新构建测试栈
  • 以常规方式运行测试

您甚至可以并行保持多个测试栈可用,通过使用不同的env文件,例如

  • 创建一个名为.euts.env.local的文件,并向其中添加任何所需的env变量,以唯一的COMPOSE_PROJECT_NAME开头
  • 通过./teststack/teststack -e .euts.env.local build构建新的测试栈
  • 通过:./teststack/teststack -e .euts.env.local runtests运行测试

我们的向后兼容性承诺

此套餐遵守语义化版本控制原则。

然而,向后兼容性有许多不同的风味。实际上,几乎每一次更改都可能破坏应用程序。例如,如果我们向类中添加一个新方法,这将破坏扩展该类并添加了相同方法(但具有不同的方法签名)的应用程序。

本节专门用于详细说明哪些指导原则影响了为套餐的每个新版本增加主/次/修补版本号的选择。

对于使用该套餐的开发者

通过以下方式实现遵守语义化版本控制

  • 现有的迁移将继续在所有次版本和修补版本增加中工作
  • 新迁移步骤和现有迁移步骤的新支持元素可能被引入到次版本中,但不会在修补版本中引入
  • 任何针对删除的迁移步骤或步骤元素将首先在至少一个次版本中过时。发生这种情况时,该元素将立即从DSL文档中删除,并在处理它的代码库旁边添加@deprecatedBC注释。请注意,到目前为止,该库的版本是6,到目前为止几乎没有迁移元素被删除!
  • CLI命令的语法将继续在所有次版本和修补版本增加中工作
  • 现有CLI命令的新选项和新命令可能被引入到次版本中,但不会在修补版本中引入
  • 现有CLI命令的文本输出可以在任何版本中更改 - 请不要依赖于它具有固定格式来解析它
  • 由套餐发出的事件将继续在所有次版本和修补版本增加中工作
  • 可能在次版本中引入新事件,但不会在修补版本中引入

针对扩展或修改包的开发者

在包的内部结构方面,即PHP类和Symfony服务方面,情况要复杂一些。虽然我们非常小心地避免破坏扩展现有类和重新定义现有服务,但仍然发生过在补丁版本中修改现有方法签名的情况。有时,在次要版本中,现有类可能需要新的接口。

  • 任何可能对扩展或修改包的开发者产生潜在影响的更改都不应在补丁版本中发生,但可能在次要版本中发生。只有在有充分的理由进行更改的情况下(例如,大多数情况下是为了修复错误或使实现重要新功能成为可能)才会进行此类更改,并在NEWS文件中进行记录。

主要版本升级

从版本5.x升级到版本6

  • 请仔细阅读发布说明中的所有BC笔记

  • 运行名为20220101000200_FixExecutedMigrationsPaths.php的迁移,例如

      php bin/console kaliop:migration:migrate --path vendor/kaliop/ezmigrationbundle/MigrationVersions
    

从版本4.x升级到版本5

  • 请仔细阅读发布说明中的所有BC笔记

  • 除非你有以下情况,否则不需要其他操作

    • 扩展迁移包代码或API的代码
    • 旧的迁移,你想再次使用更新后的包,其中包含字符串'[reference:xxx]',其中'xxx'代表任意字符序列

    在这两种情况下,解决方案是对你的代码/迁移进行手动更改。

从版本3.x升级到版本4

  • 请仔细阅读发布说明中的所有BC笔记

  • 除非你有以下情况,否则不需要其他操作

    • 扩展迁移包代码或API的代码
    • 依赖于解析migrate命令输出并依赖于其确切格式的代码

    在这两种情况下,解决方案是对你的代码进行手动更改。

从版本2.x升级到版本3

  • 请仔细阅读发布说明中的所有BC笔记

  • 除非你有以下情况,否则不需要其他操作

    • 使用扩展版本1.x或2.x生成的迁移定义,尚未应用
    • 扩展迁移包代码或API的代码

    在这两种情况下,解决方案是对你的代码/迁移进行手动更改。

从版本1.x升级到版本2

请阅读专门的文档页面

License Latest Stable Version Total Downloads

Build Status Scrutinizer Code Quality Code Coverage