Ścieżka zasobów w plikach CSS w Symfony 2

101

Problem

Mam plik CSS z pewnymi ścieżkami (dla obrazów, czcionek itp. url(..)).

Struktura mojej ścieżki jest następująca:

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

Chcę odwoływać się do moich obrazów w arkuszu stylów.

Pierwsze rozwiązanie

Zmieniłem wszystkie ścieżki w pliku CSS na ścieżki bezwzględne. To nie jest rozwiązanie, ponieważ aplikacja powinna (i musi!) Pracować również w podkatalogu.

Drugie rozwiązanie

Użyj Assetic z filter="cssrewrite".

Więc zmieniłem wszystkie moje ścieżki w moim pliku CSS na

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

do reprezentowania rzeczywistej ścieżki z katalogu zasobów do /web/imageskatalogu. To nie działa, ponieważ cssrewrite generuje następujący kod:

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

co jest oczywiście złą ścieżką.

Po assetic:dumputworzeniu tej ścieżki, która nadal jest błędna:

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

Kod gałązki Assetic:

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

Obecne (trzecie) rozwiązanie

Ponieważ wszystkie pliki CSS kończą się na /web/css/stylexyz.css, zmieniłem wszystkie ścieżki w pliku CSS na względne:

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

To (złe) rozwiązanie działa, z wyjątkiem devśrodowiska: ścieżka CSS jest, /app_dev.php/css/stylexyz.cssa zatem ścieżka obrazu wynikająca z tego jest /app_dev.php/images/myimage.png, co powoduje, że plik NotFoundHttpException.

Czy jest lepsze i działające rozwiązanie?

apfelbox
źródło
1
Opublikowałem swoje rozwiązanie tutaj: stackoverflow.com/q/9501248/1146363
Cerad
Czy to faktycznie rozwiązuje problem ze ścieżkami podczas używania app_dev.php?
apfelbox

Odpowiedzi:

194

Natknąłem się na ten sam problem.

W skrócie:

  • Chcesz mieć oryginalny CSS w „wewnętrznym” katalogu (Zasoby / aktywa / css / a.css)
  • Chcesz mieć obrazy w katalogu „public” (Resources / public / images / devil.png)
  • Chcąc, aby gałązka wzięła ten CSS, przekompilowała go do web / css / a.css i sprawiła, że ​​wskazywał obraz w /web/bundles/mynicebundle/images/devil.png

Wykonałem test z WSZYSTKIMI możliwymi (rozsądnymi) kombinacjami następujących elementów:

  • @notacja, notacja względna
  • Parse z cssrewrite, bez tego
  • Tło obrazu CSS a bezpośredni tag <img> src = do tego samego obrazu co CSS
  • CSS parsowany z asetycznym, a także bez parsowania z bezpośrednim wyjściem assetic
  • A wszystko to pomnożone przez wypróbowanie Resources/public/css„katalogu publicznego” (as ) z CSS i katalogu „prywatnego” (as Resources/assets/css).

Dało mi to w sumie 14 kombinacji na tej samej gałązce, a ta trasa została wypuszczona z

  • „/app_dev.php/”
  • „/app.php/”
  • i "/"

dając w ten sposób 14 x 3 = 42 testy.

Ponadto wszystko to zostało przetestowane pod kątem działania w podkatalogu, więc nie ma sposobu, aby oszukać, podając bezwzględne adresy URL, ponieważ po prostu by nie działały.

Testy obejmowały dwa nienazwane obrazy, a następnie elementy div nazwane od „a” do „f” dla CSS zbudowanego z folderu publicznego i nazwane od „g do„ l ”dla plików zbudowanych ze ścieżki wewnętrznej.

Zauważyłem, co następuje:

Tylko 3 z 14 testów zostały poprawnie wyświetlone na trzech adresach URL. ŻADNE nie pochodziło z folderu „wewnętrznego” (zasoby / zasoby). Warunkiem wstępnym było posiadanie wolnego CSS PUBLIC, a następnie zbudowanie go z wykorzystaniem Assetic FROM.

Oto wyniki:

  1. Wynik uruchomiony z /app_dev.php/ Wynik uruchomiony z /app_dev.php/

  2. Wynik uruchomiony z /app.php/ Wynik uruchomiony z /app.php/

  3. Wynik uruchomiony z / wprowadź opis obrazu tutaj

Więc ... TYLKO - Drugi obraz - Div B - Div C to dozwolone składnie.

Tutaj jest kod 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>

Plik 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;
}

Oraz a.css, b.css, c.css itd .: wszystkie identyczne, wystarczy zmienić kolor i selektor CSS.

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

Struktura „katalogów” jest następująca:

Katalogi Katalogi

Wszystko to przyszło, ponieważ nie chciałem, aby poszczególne oryginalne pliki były ujawniane publicznie, szczególnie gdybym chciał grać z filtrem „less”, „sass” lub podobnym… Nie chciałem, aby moje „oryginały” były publikowane, tylko skompilowany.

Ale są dobre wieści . Jeśli nie chcesz mieć „wolnego CSS” w publicznych katalogach ... zainstaluj je nie z --symlink, ale naprawdę wykonując kopię. Gdy „assetic” zbuduje złożony CSS, możesz USUNĄĆ oryginalny CSS z systemu plików i pozostawić obrazy:

Proces kompilacji Proces kompilacji

Uwaga Robię to dla --env=prodśrodowiska.

Tylko kilka myśli końcowych:

  • To pożądane zachowanie można osiągnąć, umieszczając obrazy w katalogu „public” w Git lub Mercurial, a „css” w katalogu „asset”. Oznacza to, że zamiast umieszczać je „publicznie”, jak pokazano w katalogach, wyobraź sobie a, b, c ... rezydujące w „aktywach” zamiast „publiczne”, niż mieć swój instalator / wdrażający (prawdopodobnie skrypt Bash ) umieszczenie CSS tymczasowo w katalogu „public”, zanim assets:installzostanie wykonane, assets:installnastępnie assetic:dump, a następnie automatyzacja usuwania CSS z katalogu publicznego po assetic:dumpwykonaniu. Dałoby to DOKŁADNIE zachowanie pożądane w pytaniu.

  • Innym (nieznanym, jeśli to możliwe) rozwiązaniem byłoby zbadanie, czy „zasoby: instalacja” może przyjmować tylko „publiczne” jako źródło, czy też „zasoby” jako źródło do publikacji. Pomogłoby to w przypadku zainstalowania z --symlinkopcją podczas programowania.

  • Dodatkowo, jeśli zamierzamy skrypty usuwania z katalogu „publicznego”, to znika potrzeba przechowywania ich w osobnym katalogu („asset”). Mogą żyć jako „publiczne” w naszym systemie kontroli wersji, ponieważ zostaną upuszczone po wdrożeniu do publicznego. Pozwala to również na --symlinkużytkowanie.

ALE ZAWSZE, OSTROŻNIE TERAZ: Ponieważ obecnie nie ma już oryginałów ( rm -Rf), są tylko dwa rozwiązania, a nie trzy. Działający element „B” już nie działa, ponieważ było wywołaniem asset () przy założeniu, że był oryginalny zasób. Tylko "C" (skompilowana) będzie działać.

Więc ... jest TYLKO KOŃCOWY ZWYCIĘZCA: Div "C" pozwala DOKŁADNIE o to, o co proszono w temacie: Kompilować, szanować ścieżkę do obrazów i nie ujawniać publicznie oryginalnego źródła.

Zwycięzcą jest C

Zwycięzcą jest C

Xavi Montero
źródło
3
Linki do obrazków z poprzedniego postu: 1) Wynik uruchomiony z /app_dev.php/ , 2) Wynik uruchomiony z linkiem /app.php/ , 3) Wynik uruchomiony z / link , 4) Link do katalogów , 5) Link do procesu kompilacji 6) Kto jest zwycięzcą Link
Xavi Montero
1
A jeśli chcesz dodać obraz z innego pakietu, zamiast background-image: url('../images/devil.png');używać tegobackground-image: url('../../../bundles/frontendlayout/images/devil.png');
Xavi Montero
1
Działa również łącząc „cssrewrite” z „less”:{% stylesheets filter="cssrewrite,less" "bundles/frontendlayout/less/layout.less" %} <link href="{{ asset_url }}" rel="stylesheet" type="text/css" /> {% endstylesheets %}
Xavi Montero
1
Jest to odnotowane w dokumentacji symfony. Zobacz tutaj
Noah Duncan
17

Filtr cssrewrite nie jest na razie zgodny z notacją @bundle. Masz więc dwie możliwości:

  • Odwołaj się do plików CSS w folderze internetowym (po console assets:install --symlink web:)

    {% stylesheets '/bundles/myCompany/css/*." filter="cssrewrite" %}
  • Użyj filtra cssembed, aby osadzić obrazy w CSS w ten sposób.

    {% stylesheets '@MyCompanyMyBundle/Resources/assets/css/*.css' filter="cssembed" %}
jeremymarc
źródło
Dziękuję za Twój komentarz. Drugie rozwiązanie brzmi całkiem nieźle, jeśli masz tylko małe obrazy. Jednak nie czułbym się komfortowo umieszczając w pliku CSS ponad 100 000 obrazów.
apfelbox
9

Opublikuję, co zadziałało, dzięki @ xavi-montero.

Umieść swój CSS w Resource/public/csskatalogu pakietu i powiedzmy swoje obrazy Resource/public/img.

Zmień asetyczne ścieżki do formularza 'bundles/mybundle/css/*.css'w swoim układzie.

W config.yml, dodaj regułę css_rewritedo assetic:

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

Teraz zainstaluj zasoby i skompiluj za pomocą assetic:

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

Jest to wystarczająco dobre dla pola programistycznego i --symlinkjest przydatne, więc nie musisz ponownie instalować swoich zasobów (na przykład, dodawać nowy obraz) po wejściu przez app_dev.php.

W przypadku serwera produkcyjnego właśnie usunąłem opcję `` --symlink '' (w moim skrypcie wdrożeniowym) i na końcu dodałem następujące polecenie:

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

Wszystko skończone. Dzięki temu możesz używać takich ścieżek w plikach .css:../img/picture.jpeg

ChocoDeveloper
źródło
5

Miałem ten sam problem i właśnie próbowałem użyć następującego rozwiązania jako obejścia. Wydaje się, że jak dotąd działa. Możesz nawet utworzyć fikcyjny szablon, który zawiera tylko odniesienia do wszystkich tych statycznych zasobów.

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

Zwróć uwagę na pominięcie jakiegokolwiek wyjścia, co oznacza, że ​​nic nie pojawia się w szablonie. Kiedy uruchamiam assetic: dump, pliki są kopiowane do żądanej lokalizacji, a css zawiera pracę zgodnie z oczekiwaniami.

Cowlby
źródło
1
Możesz użyć wpisu konfiguracji dla nazwanego zasobu i nie musisz uwzględniać go w szablonach. I tak zrzuci symfony.com/doc/current/cookbook/assetic/ ...
venimus
3

Jeśli może to komuś pomóc, bardzo się zmagaliśmy z Assetic i teraz robimy następujące rzeczy w trybie deweloperskim:

  • Skonfiguruj tak, jak w przypadku zrzucania plików aktywów w środowisku deweloperskim, więc config_dev.ymlskomentowaliśmy:

    #assetic:
    #    use_controller: true

    A w routing_dev.yml

    #_assetic:
    #    resource: .
    #    type:     assetic
  • Określ adres URL jako bezwzględny z katalogu głównego sieci. Na przykład background-image: url("/bundles/core/dynatree/skins/skin/vline.gif");Uwaga: wskazuje na nasz katalog główny sieci vhost web/.

  • Brak użycia filtra cssrewrite

user1041440
źródło
3
Jest to ważne rozwiązanie, ale tylko wtedy, gdy nie będzie służyć pliki z podkatalogu, na przykład: http://example.org/sub/.
apfelbox
1

Często zarządzam wtyczką css / js za pomocą programu Composer, który instaluje go u dostawcy. Dowiązuję je do katalogu web / bundles, co pozwala kompozytorowi aktualizować pakiety w razie potrzeby.

przykład:

1 - dowiązanie symboliczne raz w ogóle (użyj polecenia fromweb / bundles /

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

2 - użyj zasobu w razie potrzeby, w szablonie gałązki:

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

Pozdrowienia.

Jean-Luc Barat
źródło