如何安装包含不同版本的Symfony的模块?


17

我是CiviCRM项目的开发人员和维护人员。我们一直在尝试制作Drupal 8版本的CiviCRM,并且还有很长的路要走。我们正在为我们的集体键盘而战,试图找出该项目的主要障碍。

CiviCRM使用Symfony已有一段时间了,所包含的版本与Drupal附带的版本有所不同。

我们可以在Drupal 8上安装CiviCRM,但是在安装之后,我们将无法安装其他任何Drupal模块。

我认为这归结为某种情况,即Symfony的CiviCRM版本先于Drupal版本加载,这会引起问题。

有谁知道Drupal 8模块所包含的Symfony版本与Drupal随附的模块版本不同?

最近,我遇到了路德维希项目。该模块允许在扩展类中ServiceProviderBase注册名称空间。

Drupal 8版本的CiviCRM模块是否可能包括定义一个CivicrmServiceProvider类的CivicrmServiceProvider.php文件和一个register()添加容器名称空间以使其工作的方法?

许多CiviCRM文件都use包含以Symfony开头的Drupal之类的语句,例如here

实际上,我们将CiviCRM Core放入Drupal doc_root / libraries文件夹中,并使用库模块。

如果有人想看看我们到目前为止所得到的,这是CiviCRM Drupal模块8.x版本的存储库。如果有人为此拥有万灵药,我可以告诉您,我们社区中会有很多快乐的人。因此,如果您知道如何帮助我们,请这样做。

CiviCRM确实会安装,并且CiviCRM页面也能正常工作。无法正常工作的是,在安装CiviCRM之后,我们无法通过admin / modules页面安装其他模块。据我所知,这是唯一被破坏的东西。在安装CiviCRM之后,也可以使用Drush安装模块。

在安装CiviCRM之后尝试安装另一个模块会导致以下错误:

PHP致命错误:在第206行上的/var/www/html/civi-for-d8/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php中调用未定义的方法Symfony \ Component \ DependencyInjection \ Definition :: setFactory()

那是在Drupal 8.3.5中。尝试将用于Drupal 8的CiviCRM安装到干净的Drupal 8.4-dev实例中会导致以下错误:

Drupal \ Component \ Serialization \ Exception \ InvalidDataTypeException:保留指示符“ @”无法启动普通标量;您需要在第8行引用标量(在“参数:[@ string_translation,@ civicrm.page_state]”附近)。在Drupal \ Component \ Serialization \ YamlSymfony :: decode()中(/var/www/html/drupal84/core/lib/Drupal/Component/Serialization/YamlSymfony.php中的第40行)。


在手机上,但是什么版本的Symfony?8.4将使用3.x,这是v2的跳转。
马特·格拉曼

我们的CiviCRM版本为2.5.0
jackrabbithanna

有关此问题的一些文档:issue.civicrm.org/jira/browse/CRM-17652 ....一个人报告说他没有看到问题,但我不确定,尝试这样做的其他所有人都遇到错误就像那里报道的那样
-jackrabbithanna

4
我认为这是不可能的。Drupal 8.4实际上已经切换到了Symfony3,尽管仍然有与drush相关的类似讨论,但问题仍然存在。无法加载两个不同的symfony版本,要么破坏集成,要么破坏Drupal。也许symfony3不会在8.4中,但是对symfony2的安全支持将在Drupal8安全支持之前终止,因此在某些时候,我们将不得不切换
Berdir

1
@Berdir可能是一个很好的答案?
克莱夫(Clive)

Answers:


8

因此,我认为,如果通过作曲家(即composer require civicrm/civicrm-core,在Drupal根目录中)将CiviCRM安装到Drupal 8 中,并且CiviCRM对Symfony的使用与Symfony 2.8或3.x兼容(即,不使用不推荐使用的功能),则可以使用。

这将使所有内容都安装在Drupal的供应商目录中,而不是两个目录中,这意味着CiviCRM将在Drupal 8中使用Symfony版本。但是,如果CiviCRM与以后的Symfony版本兼容(即使它为Drupal捆绑了较旧的版本)。 6&7和其他CMS),应该没问题。

我认为?

更新:是的,它有效-我尝试了。:-)我最初将以下内容发布在CiviCRM问题队列(CRM-17652)中,但是为了完整起见,在此处重新发布。

大主意:

由于作曲家对很多人来说是相当陌生的,我将逐步尝试,从一些高级作曲家的东西一直到可以在CiviCRM中完成的一种方式:

  • Composer允许应用程序需要其需要的库(当然,库也可能需要其他库)。
  • 图书馆有一个composer.json文件,该文件说明了它还需要其他哪些图书馆以及与哪个版本兼容(但不一定是特定的单个版本-通常是一系列版本,例如^2.4.3说最低为2.4.3,最高为(但不是包括)3.0.0)
  • 应用程序具有composer.json,它类似地描述了所需的库以及与一系列版本的兼容性,但是该范围确实有助于更新。应用程序还将具有composer.lock,它是一组特定的各个版本
  • 库也可以有一个composer.lock来进行自己的测试或分发(例如使用捆绑的依赖关系构建发行版tarball),但是当应用程序需要给定的库时,可以忽略此操作(请参阅https://getcomposer.org/doc/02) -libraries.md#lock-file
  • 当应用程序需要新的库时,作曲家会在应用程序需要的所有内容(包括已安装的所有库及其依赖项)与新库之间找到版本兼容性的交集,可能会进行一些更新以使所有内容对齐(或如果找不到兼容的版本就会出错)
  • 在这种情况下,CiviCRM是一个库,一个特定的Drupal 8站点是应用程序(Drupal核心本身是一个库)
  • CiviCRM可能会说它^2.5在composer.json中“需要” Symfony ,这意味着它与2.5.0直至(但不包括)3.0.0版本兼容。
  • 当Drupal 8站点要使用CiviCRM时,站点管理员composer require civicrm/civicrm-core会要求CiviCRM库及其所有依赖项。如果CiviCRM与Symfony 2.8兼容(如Drupal 8.3.x中使用的那样),则可以使用Drupal的单个Symfony 2.8安装并正常工作。所有依赖项最终都在Drupal的供应商目录中。
  • 但是,CiviCRM可以将Symfony 2.5保留在其composer.lock中,这意味着测试将使用该文件,而Drupal 6和7以及其他CMS的压缩包将捆绑Symfony 2.5

提案:

  1. 更新CiviCRM的composer.json,以便基于作曲家的CMS像Drupal 8都可以将它用作库(但将来其他人可能会以这种方式使用-作曲家越来越受欢迎)
  2. 确保CiviCRM内核与Symfony 2.8和3.0(分别由Drupal 8.3.x和8.4.x使用)兼容,但是将“官方支持”版本(当前为Symfony 2.5)保留在composer.lock中以进行测试和tarball进行分发。与多个Symfony版本兼容可能并不像听起来那么难-有许多与Symfony 2.8和3.0兼容的库。可能只是避免使用不推荐使用的方法/类/功能!composer.json将需要更新以反映这一点
  3. 使用作曲家将CiviCRM库安装在Drupal 8上,而不是复制到库目录中。这正在成为在Drupal 8中安装第三方PHP库的常规方法(例如,Drupal Commerce广泛使用了该方法)

对于基于作曲家的CMS,我真的认为这是正确的方法。尽管此问题目前正在影响Symfony和Drupal,但是随着PHP社区开始通过作曲者使用越来越多的第三方库,这很可能会影响其他CMS并引起其他版本冲突。

一些工作代码进行测试:

因此,正如所承诺的,我实际上在一定程度上可以做到这一点:-)我完全是从Drupal / Composer / Symfony的角度出发的-我没有大量的CiviCRM经验,所以可能有一些以下是执行我的流程的更好方法。我欢迎任何建议!

  1. 下载并安装Drupal 8.3.5(或Drupal 8.4.x的最新开发!)
  2. 进入外壳程序的根目录,然后运行以下命令以通过composer安装CiviCRM:https ://gist.github.com/dsnopek/56311dbea347874e75180883efabb620
  3. 如果使用Apache,请删除vendor / .htacess文件。这是Drupal的一项安全措施,可防止加载CSS / JS之类的资源。这将需要与Drupal项目进行一些合作,以找到适当的解决方案,因为完全删除此文件在生产中是个坏主意。请参阅:vendor / .htaccess阻止来自作曲家库的CSS / JS资产
  4. 进入/ modules目录并执行 git clone https://github.com/dsnopek/civicrm-drupal.git --branch composer-library
  5. 转到“扩展”页面(/admin/modules)并安装CiviCRM模块
  6. 通过Drush清除drupal缓存(drush cr
  7. 根据CRM-19878注销并再次登录
  8. CiviCRM有效!:-)

完成所有这些之后,CiviCRM将使用Drupal的Symfony 2.8和Drupal供应商目录中的依赖项,并且不会从其自己的供应商目录中加载任何内容。头晕!

我测试了启用“电话”模块的能力,这些模块在进行这些更改之前就失败了(请参阅我的重现步骤),但可以正常使用。:-)


因此,这是使用composer与此相关的所有问题。...是否可能有一个软件包使用Symfony 2.8,而另一个软件包使用Symfony 3.2 ....
jackrabbithanna

要始终使用Drupal 8/9所使用的Symfony版本,就很难对CiviCRM进行机构抵制。
jackrabbithanna

1
“使用composer ....有可能一个软件包使用Symfony 2.8,而另一个软件包使用Symfony 3.2”->否,PHP不能有两个同名类。这并不是真正的作曲家。
David Snopek '17

“要始终使用Drupal 8/9所使用的Symfony版本,要求CiviCRM进行机构抵制非常困难”->上游CiviCRM核心所需要的就是该代码与后来在Drupal中使用的Symfony 兼容。默认情况下,它不必捆绑或使用它,只需兼容即可。避免不推荐使用的方法/类/功能。
David Snopek '17

我明白了为什么有人会对并行运行Symfony的两个主要版本感兴趣— SemVer sorta暗示了这种必要性。但是我认为重要的是,大量的Symfony组件在v2 / v3中是相似的,并且Civi对v2的集成相当适度。因此,我对拥有或实现与两者兼容的PHP代码感到乐观。恕我直言,真正的工作是更新发行渠道和目录结构。
Tim Otten

5

我认为这是不可能的。

Drupal 8.4实际上已经切换到了Symfony 3,尽管仍然有与drush相关的类似讨论,但也存在相同的问题。请参阅Drush 8.x未安装Drupal 8.4.x和Drush master未安装Drupal 8.3.xSymfony组件已更新为3.2.6。

无法加载两个不同的symfony版本,要么破坏集成,要么破坏Drupal。也许symfony3不会在8.4中,但是对symfony2的安全支持将在Drupal8安全支持之前终止,因此在某些时候,我们将不得不切换。


嗯.....除了从admin / modules安装模块以外,所有工作都可以正常进行。所以我不相信它是不可能的。为什么不可能呢?
jackrabbithanna

1
您不能同时加载同一类的两个不同版本,这是不可能的。该错误听起来与我预期会发生的完全一样。您设法首先加载了2.5版的Definition类,然后Drupal中断了,因为它希望存在实际上不存在的方法。随着Drupal切换到Symfony 3,差异会变得更大。我不太明白为什么您坚持使用2.5,而2.8是次要更新,应该向后兼容(但您发现的却不是这样)。因此,您应该能够将CiviCRM更新为要求2.8?
伯迪尔

1
正如我在评论中提到的那样,我假设您不希望我回答,但这并不能改变它。您提到的所有项目都不使用symfony(joomal似乎使用了少数可能不会冲突但最终可能会冲突的组件),因此您无法进行比较。从技术上讲,加载同一个类的两个冲突版本是不可能的,没有任何改变。这就是为什么依赖关系是一个复杂的业务,也是作曲家存在的原因。与其使用库,
不如

2
此外,根据symfony.com/roadmap?version=2.5#checker,对Symfony 2.5的安全支持于2015年结束,这意味着CiviCRM建立在不安全且过时的symfony版本上。仅凭这一点就足以说服他们,至少对于2.8版而言,有必要进行更新,而不仅仅是Drupal8。
贝迪尔

1
@DavidSnopek是的,您在回答中写的内容基本上也是我在评论中提到的内容,但是只要CiviCRM的composer.json为其symfony组件指定“〜2.5.0”,那将是行不通的。见github.com/civicrm/civicrm-core/blob/master/composer.json。因此,我的回答“您不能使用两个不同的版本”仍然是正确的恕我直言,您只能改进/更新civicrm中的版本约束,然后通过composer安装并使用相同版本。
贝迪尔

1

从理论上讲,这里唯一的问题是文件位置和类命名空间。不幸的是,我在作曲家中唯一知道的用于执行此操作的工具无法让您针对每个VERSION进行指定,而仅针对套件名称进行指定。

您是否尝试过将其设置为完全独立的自动装带器?


您能否详细解释您的意思?
jackrabbithanna

getcomposer.org/doc/faqs/…是如何进行自定义位置。我见过人们叉一个项目只是为了使这成为可能...还有getcomposer.org/doc/06-config.md#prepend-autoloader用于使作曲家的自动加载器分离的选项。最后,自动加载器只是一个php文件,因此您可以编写自己的自动加载器,该自动加载器根据您喜欢的因素决定要包含哪个自动加载器。
Ohthehugemanatee


请注意,ATM没有基于Composer的安装方法来使用D8安装Civi。尽管我也许是完成此任务的一种方法。这就是问题中提到的ServiceProvider对象所要解决的问题,例如向Drupal添加PSR-4名称空间以指向CiviCRM库...如果这样做,Civi是否需要从“使用Symfony \”更改其所有文件。 ....”以“使用Civicrm \ Symfony \ ..”?请原谅我对作曲家的无知。
jackrabbithanna
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.