Symfony 2中CSS文件中资产的路径


101

问题

我有一个CSS文件,其中包含一些路径(用于图像,字体等。url(..))。

我的路径结构是这样的:

...
+-src/
| +-MyCompany/
|   +-MyBundle/
|     +-Resources/
|       +-assets/
|         +-css/
|           +-stylesheets...
+-web/
| +-images/
|   +-images...
...

我想在样式表中引用我的图像。

第一个解决方案

我将CSS文件中的所有路径更改为绝对路径。这不是解决方案,因为应用程序也应该(并且必须!)也在子目录中工作。

第二解决方案

与一起使用Assetic filter="cssrewrite"

所以我将我的CSS文件中的所有路径更改为

url("../../../../../../web/images/myimage.png")

代表从我的资源目录到/web/images目录的实际路径。这不起作用,因为cssrewrite会生成以下代码:

url("../../Resources/assets/")

这显然是错误的道路。

assetic:dump创建此路径后,这仍然是错误的:

url("../../../web/images/myimage.png")

Assetic的树枝代码:

{% stylesheets
    '@MyCompanyMyBundle/Resources/assets/css/*.css'
    filter="cssrewrite"
%}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}

当前(第三)解决方案

由于所有CSS文件都以结尾/web/css/stylexyz.css,因此我将CSS文件中的所有路径都更改为相对路径:

url("../images/myimage.png")

这种(错误的)解决方案有效,但在dev环境中除外:CSS路径为/app_dev.php/css/stylexyz.css,因此由此产生的图像路径为/app_dev.php/images/myimage.png,这会导致NotFoundHttpException

有更好的可行解决方案吗?


1
我在这里发布了我的解决方案:stackoverflow.com/q/9501248/1146363
Cerad,2012年

这实际上可以解决使用时的路径问题app_dev.php吗?
apfelbox'3

Answers:


194

我遇到了非常非常相同的问题。

简而言之:

  • 愿意在“内部”目录中拥有原始CSS(资源/资产/css/a.css)
  • 愿意在“公共”目录中包含图像(资源/public/images/devil.png)
  • 愿意用那个树枝来获取CSS,将其重新编译为web / css / a.css并将其指向/web/bundles/mynicebundle/images/devil.png中的图像

我对以下所有可能的(合理的)组合进行了测试:

  • @符号,相对符号
  • 没有cssrewrite解析
  • CSS图像背景与直接<img>标记src =到与CSS完全相同的图像
  • CSS用资产解析,也没有用资产直接输出解析
  • 通过尝试Resources/public/css使用CSS 的“ public dir”(如)和“ private”目录(如Resources/assets/css),所有这些都成倍增加。

这使我在同一根树枝上总共获得了14种组合,这条路线从

  • “ /app_dev.php/”
  • “ /app.php/”
  • 和“ /”

因此给出了14 x 3 = 42个测试。

此外,所有这些都已经在子目录中进行了测试,因此,由于绝对无法使用绝对URL,因此无法通过提供绝对URL来欺骗。

测试是两个未命名的图像,然后对于从公用文件夹构建的CSS,将div从'a'命名为'f',对于从内部路径构建的CSS则将其命名为'g至'l'。

我观察到以下几点:

14个测试中只有3个在3个URL上正确显示。NONE来自“内部”文件夹(资源/资产)。拥有备用CSS PUBLIC,然后使用资产FROM进行构建是前提条件。

结果如下:

  1. 结果通过/app_dev.php/启动 结果通过/app_dev.php/启动

  2. 结果通过/app.php/启动 结果通过/app.php/启动

  3. 结果由/发起 在此处输入图片说明

所以...仅-第二张图片-Div B-Div C是允许的语法。

这里是TWIG代码:

<html>
    <head>
            {% stylesheets 'bundles/commondirty/css_original/container.css' filter="cssrewrite" %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

    {# First Row: ABCDEF #}

            <link href="{{ '../bundles/commondirty/css_original/a.css' }}" rel="stylesheet" type="text/css" />
            <link href="{{ asset( 'bundles/commondirty/css_original/b.css' ) }}" rel="stylesheet" type="text/css" />

            {% stylesheets 'bundles/commondirty/css_original/c.css' filter="cssrewrite" %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

            {% stylesheets 'bundles/commondirty/css_original/d.css' %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

            {% stylesheets '@CommonDirtyBundle/Resources/public/css_original/e.css' filter="cssrewrite" %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

            {% stylesheets '@CommonDirtyBundle/Resources/public/css_original/f.css' %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

    {# First Row: GHIJKL #}

            <link href="{{ '../../src/Common/DirtyBundle/Resources/assets/css/g.css' }}" rel="stylesheet" type="text/css" />
            <link href="{{ asset( '../src/Common/DirtyBundle/Resources/assets/css/h.css' ) }}" rel="stylesheet" type="text/css" />

            {% stylesheets '../src/Common/DirtyBundle/Resources/assets/css/i.css' filter="cssrewrite" %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

            {% stylesheets '../src/Common/DirtyBundle/Resources/assets/css/j.css' %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

            {% stylesheets '@CommonDirtyBundle/Resources/assets/css/k.css' filter="cssrewrite" %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

            {% stylesheets '@CommonDirtyBundle/Resources/assets/css/l.css' %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

    </head>
    <body>
        <div class="container">
            <p>
                <img alt="Devil" src="../bundles/commondirty/images/devil.png">
                <img alt="Devil" src="{{ asset('bundles/commondirty/images/devil.png') }}">
            </p>
            <p>
                <div class="a">
                    A
                </div>
                <div class="b">
                    B
                </div>
                <div class="c">
                    C
                </div>
                <div class="d">
                    D
                </div>
                <div class="e">
                    E
                </div>
                <div class="f">
                    F
                </div>
            </p>
            <p>
                <div class="g">
                    G
                </div>
                <div class="h">
                    H
                </div>
                <div class="i">
                    I
                </div>
                <div class="j">
                    J
                </div>
                <div class="k">
                    K
                </div>
                <div class="l">
                    L
                </div>
            </p>
        </div>
    </body>
</html>

container.css:

div.container
{
    border: 1px solid red;
    padding: 0px;
}

div.container img, div.container div 
{
    border: 1px solid green;
    padding: 5px;
    margin: 5px;
    width: 64px;
    height: 64px;
    display: inline-block;
    vertical-align: top;
}

还有a.css,b.css,c.css等:都相同,只是更改了颜色和CSS选择器。

.a
{
    background: red url('../images/devil.png');
}

“目录”结构为:

目录 目录

所有这一切都是因为我不想让个人原始文件公开,特别是如果我想使用“较少”过滤器或“无礼”或类似的文件...我不希望我的“原创”出版,编译一本。

但是有个好消息。如果您不希望公共目录中有“备用CSS”,请不要使用--symlink,而是要真正制作一个副本。一旦“ assetic”构建了复合CSS,就可以从文件系统中删除原始CSS,并保留图像:

编译过程 编译过程

请注意,我这样做是为了 --env=prod环境。

最后的几点想法:

  • 可以通过将图像放在GitMercurial的 “ public”目录中以及将“ assets”目录中的“ css”中来实现此期望的行为。也就是说,与其让安装程序/部署程序(可能是Bash脚本)出现,不如将a,b,c ...置于目录中所示的“ public”中,而是将它们放置在“资产”中而不是“ public”中将CSS暂时放置在assets:install执行之前的“ public”目录中,然后assets:install依次执行,然后和,然后在执行assetic:dump后自动从公共目录中删除CSS assetic:dump。这将完全达到问题中所需的行为。

  • 另一种(如果可能的话,未知)解决方案是探索“ assets:install”是仅可以将“ public”作为源,还是可以将“ assets”作为要发布的源。如果--symlink在开发时安装了选件,那将有所帮助。

  • 另外,如果我们要编写脚本来编写从“公共”目录中删除的脚本,那么,将它们存储在单独目录(“资产”)中的需求就消失了。它们可以存在于我们的版本控制系统中的“公共”内部,因为在部署到公共位置时将被删除。这也允许--symlink使用。

无论如何,现在请当心:由于现在不再有原件了(rm -Rf),因此只有两种解决方案,而不是三种。工作div“ B”不再工作,因为它是一个asset()调用,假设存在原始资产。仅“ C”(已编译的)将起作用。

所以……只有最后一个获胜者:Div“ C”可以完全满足主题中的要求:要进行编译,请遵循图像的路径,不要将原始信息公开给公众。

赢家是C

赢家是C


3
链接到先前文章的图像:1)使用/app_dev.php/启动的结果,2)使用/app.php/ 链接启动的结果,3)使用/ 链接启动的结果,4)目录链接,5)编译过程链接,6)谁是获胜者链接
Xavi Montero'4

1
而且,如果您要添加其他捆绑包中的图像,而不是使用它,请background-image: url('../images/devil.png');使用它background-image: url('../../../bundles/frontendlayout/images/devil.png');
Xavi Montero'4

1
也可以将“ cssrewrite”与“ less”组合使用:{% stylesheets filter="cssrewrite,less" "bundles/frontendlayout/less/layout.less" %} <link href="{{ asset_url }}" rel="stylesheet" type="text/css" /> {% endstylesheets %}
Xavi

1
symfony文档中对此进行了说明。看到这里
Noah Duncan 2014年

17

目前,cssrewrite过滤器与@bundle表示法不兼容。因此,您有两种选择:

  • 参考在网络文件夹中的CSS文件(后:console assets:install --symlink web

    {% stylesheets '/bundles/myCompany/css/*." filter="cssrewrite" %}
  • 使用cssembed过滤器像这样将图像嵌入CSS。

    {% stylesheets '@MyCompanyMyBundle/Resources/assets/css/*.css' filter="cssembed" %}

感谢您的评论。如果您只有很小的图像,第二种解决方案听起来不错。不过,我不太愿意在CSS文件中放置100k +张图像。
apfelbox 2012年

9

感谢@ xavi-montero,我将发布对我有用的东西。

将CSS放在bundle的Resource/public/css目录中,然后将图像放在say中Resource/public/img

'bundles/mybundle/css/*.css'在布局中将资产路径更改为form 。

在中config.yml,将规则添加css_rewrite到资产:

assetic:
    filters:
        cssrewrite:
            apply_to: "\.css$"

现在安装资产并使用资产编译:

$ rm -r app/cache/* # just in case
$ php app/console assets:install --symlink
$ php app/console assetic:dump --env=prod

这对于开发箱来说已经足够好了,并且--symlink很有用,因此当您通过进入时,您不必重新安装资产(例如,添加新映像)app_dev.php

对于生产服务器,我只是删除了“ --symlink”选项(在我的部署脚本中),并在末尾添加了以下命令:

$ rm -r web/bundles/*/css web/bundles/*/js # all this is already compiled, we don't need the originals

一切都完成了。这样,您可以在.css文件中使用如下路径:../img/picture.jpeg


5

我有同样的问题,我只是尝试使用以下方法来解决。到目前为止似乎工作正常。您甚至可以创建一个虚拟模板,其中仅包含对所有这些静态资产的引用。

{% stylesheets
    output='assets/fonts/glyphicons-halflings-regular.ttf'
    'bundles/bootstrap/fonts/glyphicons-halflings-regular.ttf'
%}{% endstylesheets %}

请注意,省略了任何输出,这意味着模板上没有任何内容。当我运行assetic:dump时,文件被复制到所需位置,并且CSS包含预期的工作。


1
您可以对命名资产使用配置条目,并且不需要将其包括在模板中。将倾倒反正symfony.com/doc/current/cookbook/assetic/...
venimus

3

如果它可以帮助某人,那么我们在Assetic方面苦苦挣扎,现在我们正在开发模式中执行以下操作:

  • 像在开发环境中的转储资产文件中一样进行设置那样进行设置config_dev.yml,我们在中进行了评论:

    #assetic:
    #    use_controller: true

    并在routing_dev.yml中

    #_assetic:
    #    resource: .
    #    type:     assetic
  • 从Web根目录将URL指定为绝对URL。例如,背景图片:url("/bundles/core/dynatree/skins/skin/vline.gif");注意:我们的虚拟主机Web根指向web/

  • 不使用cssrewrite过滤器


3
这是一个有效的解决方案,但前提是您永远不会提供子目录中的文件,例如:http://example.org/sub/
apfelbox 2012年

1

我通常使用composer管理css / js插件,并将其安装在供应商下。我将它们符号链接到web / bundles目录,这使作曲家可以根据需要更新包。

例子:

1-一次完成符号链接(使用来自web / bundles /

ln -sf vendor/select2/select2/dist/ select2

2-在树枝模板中根据需要使用资产:

{{ asset('bundles/select2/css/fileinput.css) }}

问候。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.