自定义 Symfony2 过滤器未使用自定义树枝标签触发

Posted

技术标签:

【中文标题】自定义 Symfony2 过滤器未使用自定义树枝标签触发【英文标题】:Custom Symfony2 filter not triggering with custom twig tag 【发布时间】:2015-03-14 06:34:36 【问题描述】:

TL:DR; 添加type="application/dart" 使Assetic 忽略过滤器标志filter=MyCustomFilter

删除后一个属性类型触发filter=MyCustomFilter 就好了。但我需要过滤器和属性。如何让 Assetic 在具有 type=application/dart 属性时触发我的自定义过滤器?

我相信部分问题在于它只接受type=application/javascript 或空的html type 属性来触发过滤器。我不知道从这里去哪里。


详细信息:

我想制作一个类似于javascripts 的标签,但用于 Dart 文件。

% darts
    '@AcmeBundle/Resources/dart/AcmeMain/web/main.dart'
%$ 
    <script type="application/dart" src=" asset_url "></script>
% enddarts %

我希望能够使用@ 表示法而不是/bundles/etc/

经过一番搜索,我尝试了以下方法:

我扩展了Symfony\Bundle\AsseticBundle\Twig\AsseticExtension

我继承了以下函数:

public function getTokenParsers()

    return array(
        $this->createTokenParser('javascripts', 'js/*.js'),
        $this->createTokenParser('stylesheets', 'css/*.css'),
        $this->createTokenParser('image', 'images/*', true),
    );

在我自己的子类中,我添加到父数组$this-&gt;createTokenParser('darts', 'dart/*.dart')

当我有的时候,这最初是有效的。

% darts '@MyBundle\...\main.dart' filter="MyCustomFilter" %
<script src=" asset_url "></script>

但是,引导加载程序 dart.js 需要 type="application/dart 属性才能使引导程序正常工作。

只要我添加了所需的属性,编辑源文件就不会重新编译。它几乎被忽略了。以下代码被忽略,不会触发MyCustomFilter过滤器:

% darts '@MyBundle\...\main.dart' filter="MyCustomFilter" %
<script type="application/dart" src=" asset_url "></script>

我似乎无法从这里找到下一步该去哪里,看看这一切是如何运作的本身就让人难以抗拒。我只需要将type="application/dart 识别为有效,这样我的MyCustomFilter 就会被触发。

【问题讨论】:

你看twig.sensiolabs.org/doc/advanced.html#tags了吗? 为什么不直接使用% javascripts % 标签和 dart2js 过滤器呢?这样,您的 Dart 脚本将被编译为 JavaScript,避免与浏览器的兼容性问题。 @Nic 如果没有以.dart 结尾的文件名,dartbootloader 将无法工作。我可以修改引导加载程序,但每次更新引导加载程序时,我都必须记住在我的代码工作之前修改引导加载程序。这就是为什么我想要一个合适的解决方案。 我没有使用 Dart 的经验,但是将其编译为普通的旧 javascript 是否不需要客户端编译? @Nic 从来没有任何客户端编译,飞镖代码在服务器上编译为 javascript。无论如何,它的工作方式是飞镖引导加载程序dart.js 检查未编译的main.dart。如果浏览器不支持它,它会加载main.js。现在,在资产的某个地方,当type="application/dart 添加到&lt;script&gt; 属性中时,它会阻止我的过滤器触发编译代码。所以引导加载程序无法加载main.js,因为assetic 从一开始就没有编译过。 【参考方案1】:

我建议您查看 vendor/symfony/assetic-bundle/ 文件,因为它包含 % javascripts % 实现。

从那个包的Resources/config/templating_twig.yml,他们注入了一个名为@templating.name_parser的服务,看起来这正是你要找的。​​p>

您可以尝试在控制器中执行以下操作:

var_dump(
  $this
    ->get('templating.name_parser')
    ->parse('@AcmeBundle/Resources/dart/AcmeMain/web/main.dart')
    ->getPath()
);

关于标签本身,您可以从资产包中大量复制/粘贴。并在我之前的一个答案here 上获得一些关于自定义标签的解释。

【讨论】:

我走近了,但不幸的是我偶然发现了另一个障碍。我用更多细节更新了我的答案。 在授予赏金之前,您介意最后看一下我更新的答案吗?我会很感激的。 嗨,我明天早上会检查一下。抱歉,这周没有太多时间。 嗯,你的问题看起来是飞镖特有的,而不是树枝,我真的不知道飞镖。 asset_urls 在渲染视图中是否有效? 如果不是application/javascript,twig 似乎不会触发过滤器。所以它不是特定于飞镖的。我似乎找不到在哪里可以更改它以允许 application/dart 触发资产过滤器【参考方案2】:

我认为有一个非常简单的解决方案可以解决您的问题,无需使用新的% darts % 标签。

在 Assetic 标签中,您可以指定 output 参数,该参数允许您覆盖默认输出路径(在 % javascripts % 标签的情况下为 js/*.js)。通过将output 设置为dart/*.dart,您不仅可以更改存储文件的目录,还可以更改文件扩展名。

例子:

% javascripts '@AcmeBundle/Resources/dart/AcmeMain/web/main.dart' filter="MyCustomFilter" output='dart/*.dart' %
    <script type="application/dart" src=" asset_url "></script>
% endjavascripts %

将(在生产环境中)导致:

<script type="application/dart" src="/dart/0b13818.dart"></script>

这个特性在 Symfony 文档中被描述为here,虽然它没有提到你可以改变扩展的事实。

我刚刚在我的 Symfony 应用程序中运行了一个快速测试,它似乎运行良好。

【讨论】:

我以为我试过了,但它最终将其重命名为 .dart.js... 我会再试一次。我认为我没有使用通配符,所以我想知道这是否会有所不同。 应该没什么区别。 dart/foobar.dartdart/*.dart 我都试过了,它们都生成了带有 .dart 扩展名的文件。 好的,谢谢。等我有空工作的时候我会试试的。顺便问一下,你的composer.json 文件中的 Symfony 和 Assetic 是什么版本? 我目前已经安装了 Symfony 2.6.3、Assetic 1.2.1 和 AsseticBundle 2.5.0。 composer.json 需要 Symfony 和 AsseticBundle,两者都具有版本约束 ~2.5。 Assetic 库作为 AsseticBundle 的依赖项自动安装。 我确认这很好用(在 2.5 到 2.7-dev 上检查)+1。

以上是关于自定义 Symfony2 过滤器未使用自定义树枝标签触发的主要内容,如果未能解决你的问题,请参考以下文章

Symfony2 自定义身份验证:用户登录但未通过身份验证

Symfony2:如何对自定义复合表单类型使用约束?

Grails 3.2.4:未调用自定义身份验证过滤器

在 Symfony2 的查询中使用自定义 DQL 函数

未找到具有自定义分页 404 的自定义分类和自定义帖子类型

将自定义参数传递给 Symfony2 中的自定义 ValidationConstraint