webfactory / legacy-integration-bundle
一种经过实战验证的方法,用于简化将旧应用程序逐步迁移到Symfony2堆栈的过程。
Requires
- ext-tidy: *
- doctrine/annotations: ~1.0
- psr/container: ^1.0
- psr/log: ^1.0
- symfony/config: ^4.3|^5.0|^6.0|^7.0
- symfony/dependency-injection: ^4.3|^5.0|^6.0|^7.0
- symfony/framework-bundle: 3.4.*|^4.0|^5.0|^6.0|^7.0
- symfony/http-foundation: ^4.0|^5.0|^6.0|^7.0
- symfony/http-kernel: ^4.3|^5.0|^6.0|^7.0
- symfony/service-contracts: ^1.0|^2.0|^3.0
- twig/twig: ^1.34|^2.0|^3.0
- webfactory/dom: ~1.0, >= 1.0.15
Conflicts
- php: <7.0
- dev-master
- 2.3.0
- 2.2.0
- 2.1.1
- 2.1.0
- 2.0.0
- 1.8.3
- 1.8.2
- 1.8.1
- 1.8.0
- 1.7.1
- 1.7.0
- 1.6.0
- 1.5.0
- 1.4.1
- 1.4.0
- 1.3.5
- 1.3.4
- 1.3.3
- 1.3.2
- 1.3.1
- 1.3.0
- 1.2.0
- 1.1.1
- 1.1.0
- 1.0.24
- 1.0.23
- 1.0.22
- 1.0.21
- 1.0.20
- 1.0.19
- 1.0.18
- 1.0.17
- 1.0.16
- 1.0.15
- 1.0.14
- 1.0.13
- 1.0.12
- 1.0.11
- 1.0.10
- 1.0.9
- 1.0.8
- 1.0.7
- 1.0.6
- 1.0.5
- 1.0.4
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
- dev-feature/decode_cookie_values
- dev-feature/dispatch_sub_requests
This package is auto-updated.
Last update: 2024-09-14 17:00:46 UTC
README
此包提供了一种将现有旧应用程序与Symfony2集成的方案。
简而言之,该方案是在kernel.controller事件上运行特定的事件监听器。此事件监听器将决定是否以及如何运行旧应用程序。随后将捕获旧应用程序生成的响应。
随后,在Symfony2控制器执行并渲染Twig模板后,可以检索“旧响应”的片段并将其用作输出的一部分。
这样,您可以从旧应用程序和Symfony2共存开始。然后可以逐步将功能转移到Symfony2堆栈,同时保持连贯的用户体验。
由于Symfony2推动这一过程,而Twig模板拥有控制权,决定哪些部分旧响应被使用,因此此方法自然会“成长”并远离旧应用程序,向Symfony2堆栈发展。
请注意:此包当前使用webfactory/dom,它是在PHP的DOM扩展之上的一个小型实用工具集,用于处理旧应用程序的响应并提供基于XPath的访问。它仅适用于您的旧应用程序返回格式良好的XHTML或Polyglot HTML5。
要了解更多关于此概念、其优势和注意事项,请使用您的时光机并访问2013年12月18日Symfony2用户组Colone会议。
安装
与其他任何Symfony2包一样,留给读者作为练习。
配置
webfactory_legacy_integration:
# Whether your legacy application returns text/html as XHTML 1.0 or Polyglot HTML5.
parsingMode: xhtml10|html5
# Bootstrap file for the legacy application (see next section)
legacyApplicationBootstrapFile: www/index-legacy.php
旧的“引导”文件
您必须提供一个可以include()
的单个文件,以便运行您的旧应用程序。通常您已经拥有它 - 这应该是您的旧应用程序的前端控制器。
如果您正在运行PHP < 5.4,此文件应返回旧应用程序发送的HTTP状态代码。从PHP 5.4开始,将使用http_response_code()
来检测它。
此外,由于此包将尝试使用输出缓冲捕获包括头在内的响应,因此您不得将响应体或头发送到客户端。
使用方法
一旦设置好,使用控制器上的@Dispatch注解在控制器之前运行旧应用程序,如下所示
<?php namespace Acme\My\Bundle\Controller; use Webfactory\Bundle\LegacyIntegrationBundle\Integration\Annotation as Legacy; use ... class MyController ... { /** * @Legacy\Dispatch */ public function myAction() { return ... } }
这将在进入控制器之前运行旧应用程序。整个输出包括HTTP头(重复:包括HTTP头)将被捕获并保存。除非您处理,否则不会向客户端发送任何内容。
关于旧响应体,有两种方法将旧世界与新世界混合:要么创建一个新的布局并嵌入旧应用程序的部分,要么保留旧的布局并嵌入其中新部分。以下各节将解释这两种方法。
关于HTTP头和旧应用程序发送的cookie,请确保不要错过下面解释的过滤器。例如,如果您的旧代码使用session_start()
,您可能需要转发会话cookie。
使用XPath将旧响应的部分嵌入新布局中
这是我们通常推荐的方法。如果您正在进行前端重设计的历史集成,或者如果将布局重写为Symfony世界中的布局不是太难,您应该这样做。
只有使用这种方法,您才可以在不运行旧应用程序的情况下在Symfony 2堆栈上实现新功能。
对于需要在旧系统中(部分)运行的使用案例,您可以使用由包提供的Twig全局legacyApplication
来访问响应的部分并将它们放在您的视图中。
{# you_template.html.twig #} <html> ... <body> ... <div id="content"> {{ legacyApplication.xpath('//*[@id="content"]/*') | raw }} </div> ... </body> </html>
用由Twig生成的标记替换旧响应中的任意占位符
有时您必须专注于在Symfony 2堆栈上提供新功能,而您将陷入由旧应用程序生成的页面布局。
这的缺点是每次请求都必须运行旧应用程序才能获取此布局,这在性能上是一个惩罚。即使是完全新的功能也需要每次都运行旧应用程序。
两个Twig函数webfactoy_legacy_integration_embed()
和webfactory_legacy_integration_embed_result()
有助于这种集成方式。
-
webfactory_legacy_integration_embed(placeholder, replacement)
将在旧应用程序的响应中搜索任意的placeholder
字符串。然后它将它们替换为replacement
。此函数可用于多次不同的替换。 -
webfactory_legacy_integration_embed_result()
将在执行一个或多个替换后返回最终结果。
这些替换最好保存在Twig的基础布局模板中,并映射到Twig块,如下所示
{# baseLayout.html.twig #} {{ webfactory_legacy_integration_embed('<!-- MAIN_CONTENT -->', block('main_content')) }} {{ webfactory_legacy_integration_embed_result() }}
此布局模板除了由webfactory_legacy_integration_embed_result()
提供的输出之外不执行任何其他输出。然后它可以这样扩展
{# new-functionality.html.twig #} {% extends 'baseLayout.html.twig' %} {% block main_content %} your new content here {% end block %}
这的好处是使new-functionality.html.twig
模板与其与旧应用程序的集成方式隔离开。一旦将页面布局转移到Symfony 2堆栈上,就可以更新baseLayout.html.twig
模板(当然它应该输出main_content
块!)并停止为新功能分发旧应用程序。
过滤器
LegacyApplicationDispatchingEventListener
可以接受一组必须实现Webfactory\Bundle\LegacyIntegrationBundle\Integration\Filter接口的过滤器。
一旦执行了旧应用程序,所有注册的过滤器都会传递给触发事件监听器的ControllerEvent
以及为旧应用程序创建的Response
对象。
此用例的主要用途是能够检查响应并选择将其原样发送给客户端,从而绕过执行Symfony2控制器。这样,您就可以在Symfony2中有路由/控制器来触发(或允许)执行旧应用程序中的特定使用案例,同时最初返回未修改的响应。
您可以使用webfactory_legacy_integration.filter
标签添加更多过滤器。更方便的方法是使用以下额外的注解。
过滤器注解
Webfactory\Bundle\LegacyIntegrationBundle\Integration\Annotation
命名空间包含一些您可以使用的注解,除了前面描述的@Legacy\Dispatch
注解外。
特别是,
- @Legacy\Passthru将旧应用程序的响应原样发送,因此控制器本身将永远不会运行
- @Legacy\IgnoreRedirect如果旧应用程序发送了Location:重定向头,则绕过控制器。
- @Legacy\IgnoreHeader("some-name")如果旧应用程序发送了"Some-Name:"头,则绕过控制器。这可以用来让旧应用程序控制Symfony2控制器的执行(谨慎使用)。
- @Legacy\KeepHeaders将应用旧响应中找到的所有HTTP头,并将它们添加到由Symfony控制器创建的响应中。您还可以通过
@Legacy\KeepHeaders({"X-Some-Header", "X-Some-Other"})
选择性地选择头。 - @Legacy\KeepCookies 的功能类似于
KeepHeaders
,但会查看cookie名称。
错误
我们已成功使用此包将几个应用程序和项目逐步迁移到 Symfony2 堆栈。然而,它还需要更多的关注、细致打磨和文档。欢迎为它提交PR或打开issue,表达你对它的兴趣。
哦,单元测试也会很好 :)