Путь к ресурсам в файлах CSS в Symfony 2

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.

Есть ли лучшее и рабочее решение?

apfelbox
источник
1
Я разместил свое решение здесь: stackoverflow.com/q/9501248/1146363
Cerad,
Действительно ли это решает проблему с путями при использовании app_dev.php?
apfelbox 01

Ответы:

194

Я столкнулся с той же проблемой.

Коротко:

  • Желание иметь оригинальный CSS во "внутреннем" каталоге (Resources / assets / css / a.css)
  • Готовы разместить изображения в "общедоступном" каталоге (Resources / public / images / devil.png)
  • Желая, чтобы веточка взяла этот CSS, перекомпилировала его в web / css / a.css и заставила указывать на изображение в /web/bundles/mynicebundle/images/devil.png

Я провел тест со ВСЕМИ возможными (разумными) комбинациями из следующего:

  • @notation, относительное обозначение
  • Парсить cssrewrite, без него
  • Фон изображения CSS против прямого тега <img> src = к тому же изображению, что и CSS
  • CSS анализируется с помощью сборки, а также без анализа с прямым выводом сборки
  • И все это умножается на попытки использования «общедоступного Resources/public/cssкаталога » (as ) с помощью CSS и «частного» каталога (as Resources/assets/css).

Это дало мне в общей сложности 14 комбинаций на одной ветке, и этот маршрут был запущен из

  • "/app_dev.php/"
  • "/app.php/"
  • и "/"

Таким образом, получаем 14 x 3 = 42 теста.

Кроме того, все это было протестировано для работы в подкаталоге, поэтому невозможно обмануть, указав абсолютные URL-адреса, потому что они просто не будут работать.

Тесты представляли собой два безымянных изображения, а затем div с именами от «a» до «f» для CSS, созданным ИЗ общей папки, и с именами от «g до« l »для изображений, построенных по внутреннему пути.

Я заметил следующее:

Только 3 из 14 тестов были адекватно показаны на трех URL. И НЕТ было из «внутренней» папки (Ресурсы / активы). Предварительным условием было иметь запасной CSS PUBLIC, а затем строить с помощью Assetic 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');
}

Структура «справочников» такова:

Справочники Справочники

Все это произошло, потому что я не хотел, чтобы отдельные исходные файлы были доступны публике, особенно если я хотел поиграть с фильтром "меньше", или с "sass" или подобным ... Я не хотел, чтобы мои "оригиналы" публиковались, только составлен один.

Но есть и хорошие новости . Если вы не хотите иметь "запасной CSS" в общедоступных каталогах ... устанавливайте их не вместе --symlink, а действительно создавая копию. После того, как "Assetic" построил составной CSS, вы можете УДАЛИТЬ исходный CSS из файловой системы и оставить изображения:

Процесс компиляции Процесс компиляции

Обратите внимание, я делаю это для --env=prodокружающей среды.

Несколько заключительных мыслей:

  • Это желаемое поведение может быть достигнуто, если изображения находятся в «общедоступном» каталоге в Git или Mercurial, а «css» - в каталоге «assets». То есть, вместо того, чтобы иметь их в "общедоступных", как показано в каталогах, представьте, что a, b, c ... находятся в "активах" вместо "общедоступных", чем ваш установщик / средство развертывания (возможно, сценарий Bash ) временно поместить CSS в "общедоступный" каталог перед assets:installвыполнением, затем 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/ link , 3) Результат, запущенный с помощью / link , 4) Ссылка на каталоги , 5) Ссылка на процесс компиляции , 6) Кто станет звеном
Хави Монтеро
1
И если вы хотите добавить изображение из другого пакета, вместо этого используйте background-image: url('../images/devil.png');этоbackground-image: url('../../../bundles/frontendlayout/images/devil.png');
Хави Монтеро,
1
Также работает сочетание «cssrewrite» с «less»:{% stylesheets filter="cssrewrite,less" "bundles/frontendlayout/less/layout.less" %} <link href="{{ asset_url }}" rel="stylesheet" type="text/css" /> {% endstylesheets %}
Xavi Montero
1
Это отмечено в документации Symfony. Смотрите здесь
Ной Дункан
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 более 100 тыс. Изображений.
apfelbox
9

Я опубликую, что у меня сработало, спасибо @ xavi-montero.

Поместите свой CSS в вашем Bundle в Resource/public/cssкаталоге, а также изображения, скажем Resource/public/img.

Измените ассетические пути к форме 'bundles/mybundle/css/*.css'в макете.

В 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

ChocoDeveloper
источник
5

У меня была та же проблема, и я просто попытался использовать следующее в качестве временного решения. Кажется, пока работает. Вы даже можете создать фиктивный шаблон, который просто содержит ссылки на все эти статические ресурсы.

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

Обратите внимание на отсутствие вывода, что означает, что в шаблоне ничего не отображается. Когда я запускаю Assetic: dump, файлы копируются в желаемое место, и css включает работу, как ожидалось.

Cowlby
источник
1
Вы можете использовать запись конфигурации для именованного актива, и вам не требуется включать ее в шаблоны. В любом случае он будет сбрасывать symfony.com/doc/current/cookbook/assetic/…
venimus 09
3

Если это может кому-то помочь, мы много боролись с Assetic, и теперь мы делаем следующее в режиме разработки:

  • Настроить как в Dumping Asset Files в среде разработки, так что config_dev.ymlмы прокомментировали:

    #assetic:
    #    use_controller: true

    И в routing_dev.yml

    #_assetic:
    #    resource: .
    #    type:     assetic
  • Укажите абсолютный URL-адрес из корневого веб-сайта. Например, background-image: url("/bundles/core/dynatree/skins/skin/vline.gif");Примечание: на наш веб-корень vhost указывает web/.

  • Не использовать фильтр cssrewrite

user1041440
источник
3
Это верное решение, но только если вы никогда не будете служить файлы из подкаталога, например: http://example.org/sub/.
apfelbox
1

Я обычно управляю плагином css / js с помощью композитора, который устанавливает его от поставщика. Я символически привязываю их к каталогу web / bundles, что позволяет композитору обновлять пакеты по мере необходимости.

пример:

1 - символическая ссылка один раз (используйте команду fromweb / bundles /

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

2 - использовать актив там, где это необходимо, в шаблоне веточки:

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

С уважением.

Жан-Люк Барат
источник