如何使用现有的 PHP 标头生成类函数来填充树枝模板



在现有的应用程序中,有一个函数使用类动态生成标头。

use GLOBALNAMESPACECoreHeader;

然后在体内,我们使用

<header>
<title>My Page</title>
<?php Header::setupHeader('[common],[reporthelper]') ?>
</header>

当页面在浏览器中呈现时,这将像这样构建所有标题。

<header>
<title>My Page</title> 
<link rel="stylesheet" href="/openemr/public/assets/bootstrap/dist/css/bootstrap.min.css?v=44" type="text/css">
<link rel="stylesheet" href="/openemr/public/assets/font-awesome/css/font-awesome.min.css?v=44" type="text/css">
<link rel="stylesheet" href="/openemr/public/assets/jquery-datetimepicker/build/jquery.datetimepicker.min.css?v=44" type="text/css">
<script type="text/javascript" src="/openemr/public/assets/jquery/dist/jquery.min.js?v=44"</script>

在我的模板文件中,我试过了。

{%  
include GLOBALNAMESPACE\Core\Header::setupHeader('[common],[reporthelper]')
%}

这失败了。有没有办法包含PHP类?

更新:

按照建议,在 twig 目录中创建了 HeaderExtension 类。

TwigHeaderExtension

文件内部是以下代码:

namespace Twig;
use TwigExtensionAbstractExtension;
class HeaderExtension extends AbstractExtension
{
public function getFunctions() {
return [
new TwigFunction(
'header_setup',
[OpenEMRCoreHeader::class, 'Header']
),
// add more if needed
];
}
}

在添加的方法中

$loader = new FilesystemLoader('../../templates/financialreports/insurance');
$twig = new Environment($loader, [
'cache' => 'C:tempt',
]);
return $twig->render('summaryinsurancepaid.html.twig', [
'header' => new HeaderExtension(),
'name' => 'Fabien Roger']);

现在,没有错误消息。但是,没有达到预期的结果。 似乎缺少对 setupHeader(( 的调用。 在新的TwigFunction中,"header_setup"被定义为在全局命名空间中调用的类。 但是没有任何东西可以调用类方法setupHeader((,我可以在其中添加数组setupHeader(['common'],['reporthelper'](。传入数组将返回所需的结果。

在此页面上的示例中 https://symfony.com/doc/current/templating/twig_extension.html。

他们使用 TwigFilter 而不是 TwigFunction 在运行时引入类。 我改变了这一行,从这个

'header' => new HeaderExtension()

对此。

'header' => new HeaderExtension('header_setup'),

没有错误,但也没有标题。所以,我从这里更改了模板。

{{ header }}

对此:

{{ header(setupHeader(['common'],['reporthelper'])) }}

没有错误消息,也没有标头。 更新结束。

根据Header提供的逻辑 - 特别是关于它创建的输出 - 有不同的方法:

通过 twig 函数公开选择Header方法

namespace AppTwig;
class HeaderExtension extends TwigExtensionAbstractExtension {
public function getFunctions() {
return [
new TwigTwigFunction(
'header_setup', 
[GLOBALNAMESPACECoreHeader::class, 'setupAssets']
),
// add more if needed
];
}
}

然后在模板中将其用作

{{ header_setup('[common],[reporthelper]') }}

通过一个树枝函数公开Header的静态函数

稍微解决方法可能是另一种与以前几乎相同的TwigFunction的方法,但使用:

new TwigTwigFunction('header', function($func, ...$args) {
return call_user_func_array([GLOBALNAMESPACECoreHeader::class, $func], $args);
}

这将允许:

{{ header('setupAssets', '[common],[reporthelper]') }}

这显然是一种更奇怪的语法。 你可以更进一步

公开所有类/实例函数

new TwigTwigFunction('call', function($class, $func, ...$args) {
return call_user_func_array([$class, $func], $args);
}

然后用作:

{{ call('GLOBALNAMESPACE\Core\Header', 'setupAssets', '[common],[reporthelper]') }}

(如果有人能够编辑模板,这显然会增加安全风险,因为现在您可以在任何地方调用所有静态函数......

Header改写成更美丽的东西

我认为Header的一些(如果不是全部(功能是非常基本的,可以表示为树枝模板本身,例如......

{% set targets = targets ?? ['common'] %}{# <-- defaults for every template? #}
{% if 'common' in targets %}
<link rel="stylesheet" href="/openemr/public/assets/bootstrap/dist/css/bootstrap.min.css?v=44" type="text/css">
<link rel="stylesheet" href="/openemr/public/assets/font-awesome/css/font-awesome.min.css?v=44" type="text/css">
<link rel="stylesheet" href="/openemr/public/assets/jquery-datetimepicker/build/jquery.datetimepicker.min.css?v=44" type="text/css">
<script type="text/javascript" src="/openemr/public/assets/jquery/dist/jquery.min.js?v=44"></script> 
{% endif %}
{% if 'reporthelper' in targets %}
<script type="text/javascript" src="/openemr/public/assets/reporthelper/..."></script>
{% endif %}

等等。但是,我很确定您正在寻找的功能是否可以通过 webpack encore 获得

更新:如何将Twig扩展添加到您的Symfony项目并使用它

假设你不只是使用Symfony组件(在这种情况下,以下内容将不适用(,有几种方法应该这样做:

1.实际延伸树枝

扩展 Twig 在 Symfony 中通过向服务添加twig.extension(即 Twig 扩展(来工作,因此,在您的服务 YAML 中(请注意根据需要将缩进与空格匹配(:

services:
AppTwigHeaderExtension:
tags: ['twig.extension']

如果你不希望这个扩展是全局可用的,你可以使用Symfony的依赖注入来获取twig服务并添加扩展

public function yourRouteAction(
TwigEnvironment $twig
/* your other parameters */
) {
$twig->addExtension(new HeaderExtension());

// don't *have* to use $twig here, symfony provides the very
// same twig environment wherever it's referenced. this is not true
// if you create one on the fly with new Twig...
return $this->render(...); 

只是为了明确这一点:添加扩展在 twig 中提供了函数,您根本不需要在渲染调用中添加它!

2. 修复扩展/用法

现在您实际上将扩展添加为扩展,而不仅仅是每次都必须手动添加的变量,将有一个可用的函数:

{{ header_setup(...) }}

正如我已经写过的,你必须提供一个可调用的参数作为TwigFunction构造函数的第二个参数。自从上次你改变了你想打电话的内容,所以我更新了我的答案。可调用对象的结构为:[classname, functionname]静态调用,因此在您的情况下:[Header::class, 'setupAssets'].这意味着,你在Twig 中的调用是

{{ header_setup(a) }} {{ header_setup(b,c,d) }} {{ header_setup([e,f]) }}

这将转化为

Header::setupAssets(a) // and
Header::setupAssets(b,c,d) // and
Header::setupAssets([e,f])

分别。

这也假设你的 Header::setupAssets((返回文本,以便将其插入正确的位置。我不太确定树枝如何回显内容,但是如果您的 Header 立即回显所有内容而不是返回代码建议的内容,您可能必须使用输出缓冲来捕获它:

new TwigTwigFunction(
'header_setup', 
function(...$args) {
ob_start();
call_user_func_array(
[GLOBALNAMESPACECoreHeader::class, 'setupAssets'],
$args
); // if Header::setupAssets echoes directly, it will be caught
return ob_get_clean(); // returns caught stuff
}
),

最新更新