在 Symfony2 中使用 Twig 作为 JavaScript 的资产过滤器

Posted

技术标签:

【中文标题】在 Symfony2 中使用 Twig 作为 JavaScript 的资产过滤器【英文标题】:Using Twig as an Assetic filter for JavaScript in Symfony2 【发布时间】:2013-04-08 16:12:18 【问题描述】:

有没有办法将 Twig 用作资产过滤器?

我想做的是让 Twig 将我的 javascript 文件解析为 Twig 模板,然后将它们传递给 Assetic,以便它们在生产中组合并缩小。

您可能会在想为什么我首先要这样做,所以让我跳到一个例子。


我正在用 JavaScript 制作游戏引擎,我需要有多个“类”的两个版本。 一个版本供用户使用,另一个版本供编辑器使用。这些类之一的示例是单例 World

此类的用户版本可能如下所示:

var World = function()

    // bunch of 'private' variables and functions inside closure
    var _initialised = false;
    var _worldData;
    ...

    // public functions
    this.init = function()...
    this.update = function()...
    ...

此类的编辑器版本可能如下所示:

var World = function()

    // bunch of 'private' variables and functions inside closure
    var _initialised = false;
    var _worldData;
    ...

    // bunch of new private variables and functions for editing
    var _editorserver;
    ...

    // public functions
    this.init = function()...
    this.update = function()...
    ...

    // public functions that edit the world
    this.addEntity = function()...
    this.removeEntity = function()...
    ...

使用经典的 OO 继承,我们可以将 World 定义为一个类,然后用另一个类 EditableWorld 扩展它。然而,在 JavaScript 中使用 Prototypal 继承只会继承公共函数,如果您甚至尝试扩展现有实例,您将无法访问闭包内的变量和函数。

Twig 来救援了!

使用 Twig,我们可以将多个块添加到文件中的任何类,然后创建另一个文件,使用一些扩展名定义相同的类,然后包含 那个 文件。

让我们再次将我们的基础 World 类视为 Twig 模板。

// world.js.twig
var World = function()

    // bunch of 'private' variables and functions inside closure
    var _initialised = false;
    var _worldData;
    ...

    % block extended_privates %% endblock %

    // public functions
    this.init = function()...
    this.update = function()...
    ...

    % block extended_publics %% endblock %

还有我们的扩展版本。

// editableworld.js.twig
% extends "EngineBundle::world.js.twig" %
var World = function()

    // bunch of 'private' variables and functions inside closure
    var _initialised = false;
    var _worldData;
    ...

    % block extended_privates %
    // bunch of new private variables and functions for editing
    var _editorserver;
    ...
    % endblock %

    // public functions
    this.init = function()...
    this.update = function()...
    ...

    % block extended_publics %
    // public functions that edit the world
    this.addEntity = function()...
    this.removeEntity = function()...
    ...
    % endblock %


现在问题来了:我如何让 Assetic 使用 Twig 作为过滤器,以便我可以执行以下操作:

// user version of twig template
// gameengine.html.twig

% javascripts filter="js_twig_filter"
"@EngineBundle/Resources/public/js/world.js.twig"
%
<script src=" asset_url " type="text/javascript"></script>
% endjavascripts %

// editor version of twig template
// gameeditor.html.twig

% javascripts filter="js_twig_filter"
"@EngineBundle/Resources/public/js/editableworld.js.twig"
%
<script src=" asset_url " type="text/javascript"></script>
% endjavascripts %

您可能想到的一个直接解决方案是完全放弃闭包,只将我的所有变量和函数公开,并在应该是私有的前面加上下划线。但是对我来说,这不是一个有效的解决方案,因为我不仅仅是在创建一个库。游戏引擎需要从最终用户那里关闭它的所有内部结构,以阻止所有想要篡改正在运行的引擎的确定用户(并且对于那些用户,我已经进行了服务器验证,以确保来自受感染客户端的非法操作不要通过服务器发送给其他客户端)。

感谢您的支持,我希望有人可以帮助我(在我想到这个可能的解决方案之前,我已经把头撞在墙上几天了,现在正在尝试其他想法)。

【问题讨论】:

【参考方案1】:

您需要先渲染(在控制器中)所有 *.js.twig 文件并将它们保存为 *.js 文件(在资源树的某处使用 file_put_contents() 函数)。然后将 *.js 文件加载到您的资产过滤器中。

此外,您还有许多优雅地支持 JavaScript 中的 OOP 的库/语言/帮助程序(例如 CoffeeScript、Backbone.js、Underscore.js 等)

祝你好运!

【讨论】:

以上是关于在 Symfony2 中使用 Twig 作为 JavaScript 的资产过滤器的主要内容,如果未能解决你的问题,请参考以下文章

在 Twig 模板中使用 Symfony2 控制器返回

Symfony2 在 Twig 中获取用户角色

Symfony2 - 在 TWIG 模板中获取当前 URL 或路由?

使用 Symfony2/Twig 创建引导轮播

Symfony2 中的 Twig CamelCase 过滤器

如何将 TWIG 输出渲染到变量以供以后使用(symfony2)?