如何使用现有的 PHP header 生成 class 函数来填充树枝模板
How to use existing PHP header generation class function to populate a twig template
在现有的应用程序中,有一个使用classes动态生成header的函数。
use GLOBALNAMESPACE\Core\Header;
然后在body中,我们使用
<header>
<title>My Page</title>
<?php Header::setupHeader('[common],[reporthelper]') ?>
</header>
当页面在浏览器中呈现时,这将像这样构建所有 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 classes?
更新:
按照建议,在 twig 目录中创建了 HeaderExtension class。
Twig\HeaderExtension
文件里面是这段代码:
namespace Twig;
use Twig\Extension\AbstractExtension;
class HeaderExtension extends AbstractExtension
{
public function getFunctions() {
return [
new TwigFunction(
'header_setup',
[OpenEMR\Core\Header::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' 被定义为在全局命名空间中调用到 header 的 class。
但是没有任何东西调用 class 方法 setupHeader(),我可以在其中添加数组 setupHeader(['common'],['reporthelper'])。传入数组将返回所需的结果。
在此页面的示例中 https://symfony.com/doc/current/templating/twig_extension.html。
他们使用 TwigFilter 而不是 TwigFunction 在运行时引入 class。
我改变了这一行,从这个
'header' => new HeaderExtension()
到此。
'header' => new HeaderExtension('header_setup'),
没有错误,但也没有 header。所以,我改变了这个模板。
{{ header }}
为此:
{{ header(setupHeader(['common'],['reporthelper'])) }}
没有错误消息,也没有 header。
更新结束。
根据您的 Header
确实提供的逻辑 - 特别是关于它创建的输出 - 有不同的方法:
通过 twig 函数公开 select Header
方法
namespace App\Twig;
class HeaderExtension extends \Twig\Extension\AbstractExtension {
public function getFunctions() {
return [
new \Twig\TwigFunction(
'header_setup',
[GLOBALNAMESPACE\Core\Header::class, 'setupAssets']
),
// add more if needed
];
}
}
然后在您的模板中将其用作
{{ header_setup('[common],[reporthelper]') }}
通过一个 twig 函数公开 Header
的静态函数
一个轻微的解决方法可能是另一种方法,与以前几乎相同的 TwigFunction,但使用:
new \Twig\TwigFunction('header', function($func, ...$args) {
return call_user_func_array([GLOBALNAMESPACE\Core\Header::class, $func], $args);
}
然后将允许:
{{ header('setupAssets', '[common],[reporthelper]') }}
这显然是一种更奇怪的语法。你可以更进一步
公开所有 class/instance 函数
new \Twig\TwigFunction('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.实际上延长了树枝
通过 adding twig.extension
to your service(即您的 twig 扩展)在 symfony 中扩展 twig,因此,在您的服务 yaml 中(注意根据需要将缩进与空格匹配):
services:
App\Twig\HeaderExtension:
tags: ['twig.extension']
如果你不想让这个扩展全局可用,你可以使用 symfony 的依赖注入来获取 twig 服务并添加扩展
public function yourRouteAction(
\Twig\Environment $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']
。这意味着,你在 in 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() returns 文本,以便将其插入正确的位置。我不太确定 twigs 如何回显东西,但是如果您的 Header 立即回显所有内容而不是像您的代码建议的那样返回它,您可能必须使用输出缓冲来捕获它:
new \Twig\TwigFunction(
'header_setup',
function(...$args) {
ob_start();
call_user_func_array(
[GLOBALNAMESPACE\Core\Header::class, 'setupAssets'],
$args
); // if Header::setupAssets echoes directly, it will be caught
return ob_get_clean(); // returns caught stuff
}
),
在现有的应用程序中,有一个使用classes动态生成header的函数。
use GLOBALNAMESPACE\Core\Header;
然后在body中,我们使用
<header>
<title>My Page</title>
<?php Header::setupHeader('[common],[reporthelper]') ?>
</header>
当页面在浏览器中呈现时,这将像这样构建所有 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 classes?
更新:
按照建议,在 twig 目录中创建了 HeaderExtension class。
Twig\HeaderExtension
文件里面是这段代码:
namespace Twig;
use Twig\Extension\AbstractExtension;
class HeaderExtension extends AbstractExtension
{
public function getFunctions() {
return [
new TwigFunction(
'header_setup',
[OpenEMR\Core\Header::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' 被定义为在全局命名空间中调用到 header 的 class。 但是没有任何东西调用 class 方法 setupHeader(),我可以在其中添加数组 setupHeader(['common'],['reporthelper'])。传入数组将返回所需的结果。
在此页面的示例中 https://symfony.com/doc/current/templating/twig_extension.html。
他们使用 TwigFilter 而不是 TwigFunction 在运行时引入 class。 我改变了这一行,从这个
'header' => new HeaderExtension()
到此。
'header' => new HeaderExtension('header_setup'),
没有错误,但也没有 header。所以,我改变了这个模板。
{{ header }}
为此:
{{ header(setupHeader(['common'],['reporthelper'])) }}
没有错误消息,也没有 header。 更新结束。
根据您的 Header
确实提供的逻辑 - 特别是关于它创建的输出 - 有不同的方法:
通过 twig 函数公开 select Header
方法
namespace App\Twig;
class HeaderExtension extends \Twig\Extension\AbstractExtension {
public function getFunctions() {
return [
new \Twig\TwigFunction(
'header_setup',
[GLOBALNAMESPACE\Core\Header::class, 'setupAssets']
),
// add more if needed
];
}
}
然后在您的模板中将其用作
{{ header_setup('[common],[reporthelper]') }}
通过一个 twig 函数公开 Header
的静态函数
一个轻微的解决方法可能是另一种方法,与以前几乎相同的 TwigFunction,但使用:
new \Twig\TwigFunction('header', function($func, ...$args) {
return call_user_func_array([GLOBALNAMESPACE\Core\Header::class, $func], $args);
}
然后将允许:
{{ header('setupAssets', '[common],[reporthelper]') }}
这显然是一种更奇怪的语法。你可以更进一步
公开所有 class/instance 函数
new \Twig\TwigFunction('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.实际上延长了树枝
通过 adding twig.extension
to your service(即您的 twig 扩展)在 symfony 中扩展 twig,因此,在您的服务 yaml 中(注意根据需要将缩进与空格匹配):
services:
App\Twig\HeaderExtension:
tags: ['twig.extension']
如果你不想让这个扩展全局可用,你可以使用 symfony 的依赖注入来获取 twig 服务并添加扩展
public function yourRouteAction(
\Twig\Environment $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']
。这意味着,你在 in 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() returns 文本,以便将其插入正确的位置。我不太确定 twigs 如何回显东西,但是如果您的 Header 立即回显所有内容而不是像您的代码建议的那样返回它,您可能必须使用输出缓冲来捕获它:
new \Twig\TwigFunction(
'header_setup',
function(...$args) {
ob_start();
call_user_func_array(
[GLOBALNAMESPACE\Core\Header::class, 'setupAssets'],
$args
); // if Header::setupAssets echoes directly, it will be caught
return ob_get_clean(); // returns caught stuff
}
),