Pfad der Assets in CSS-Dateien in Symfony 2

101

Problem

Ich habe eine CSS- Datei mit einigen Pfaden (für Bilder, Schriftarten usw.)url(..) ).

Meine Pfadstruktur ist wie folgt:

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

Ich möchte meine Bilder im Stylesheet referenzieren.

Erste Lösung

Ich habe alle Pfade in der CSS-Datei in absolute Pfade geändert. Dies ist keine Lösung, da die Anwendung auch in einem Unterverzeichnis arbeiten sollte (und muss!).

Zweite Lösung

Verwenden Sie Assetic mit filter="cssrewrite".

Also habe ich alle meine Pfade in meiner CSS-Datei in geändert

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

um den tatsächlichen Pfad von meinem Ressourcenverzeichnis zum Verzeichnis darzustellen /web/images. Dies funktioniert nicht, da cssrewrite den folgenden Code erzeugt:

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

Das ist offensichtlich der falsche Weg.

Nachdem assetic:dumpdieser Pfad erstellt wurde, ist dies immer noch falsch:

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

Der Zweigcode von Assetic:

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

Aktuelle (dritte) Lösung

Da alle CSS-Dateien in enden /web/css/stylexyz.css, habe ich alle Pfade in der CSS-Datei so geändert, dass sie relativ sind:

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

Diese (schlechte) Lösung funktioniert, außer in der devUmgebung: Der CSS-Pfad ist /app_dev.php/css/stylexyz.cssund daher der daraus resultierende Bildpfad /app_dev.php/images/myimage.png, was zu a führt NotFoundHttpException.

Gibt es eine bessere und funktionierende Lösung?

Apfelbox
quelle
1
Ich habe meine Lösung hier veröffentlicht: stackoverflow.com/q/9501248/1146363
Cerad
Behebt dies tatsächlich das Problem mit den Pfaden bei der Verwendung app_dev.php?
Apfelbox

Antworten:

194

Ich bin auf das sehr, sehr gleiche Problem gestoßen.

Zusamenfassend:

  • Bereit, Original-CSS in einem "internen" Verzeichnis zu haben (Ressourcen / Assets / CSS / a.css)
  • Bereit, die Bilder im "öffentlichen" Verzeichnis zu haben (Resources / public / images / devil.png)
  • Wenn Sie diesen Zweig bereitwillig nehmen, wird dieses CSS in web / css / a.css neu kompiliert und auf das Bild in /web/bundles/mynicebundle/images/devil.png ausgerichtet

Ich habe einen Test mit ALLEN möglichen (gesunden) Kombinationen der folgenden gemacht:

  • @notation, relative Notation
  • Mit cssrewrite analysieren, ohne es
  • CSS-Bildhintergrund vs direktes <img> -Tag src = auf dasselbe Bild wie CSS
  • CSS analysiert mit assetischer und auch ohne Analyse mit assetischer Direktausgabe
  • Und das alles multipliziert mit einem "öffentlichen Verzeichnis" (as Resources/public/css) mit dem CSS und einem "privaten" Verzeichnis (as Resources/assets/css).

Dies gab mir insgesamt 14 Kombinationen auf demselben Zweig, und diese Route wurde von gestartet

  • "/app_dev.php/"
  • "/app.php/"
  • und "/"

Dies ergibt 14 x 3 = 42 Tests.

Darüber hinaus wurde all dies in einem Unterverzeichnis getestet, sodass es keine Möglichkeit gibt, sich durch Angabe absoluter URLs zu täuschen, da diese einfach nicht funktionieren würden.

Die Tests bestanden aus zwei unbenannten Bildern und Divs, die von 'a' bis 'f' für das aus dem öffentlichen Ordner erstellte CSS und von 'g bis' l 'für diejenigen, die aus dem internen Pfad erstellt wurden, benannt wurden.

Ich habe folgendes beobachtet:

Nur 3 der 14 Tests wurden auf den drei URLs angemessen angezeigt. Und NONE war aus dem "internen" Ordner (Ressourcen / Assets). Es war eine Voraussetzung, das Ersatz-CSS PUBLIC zu haben und dann mit assetic FROM von dort aus zu bauen.

Dies sind die Ergebnisse:

  1. Ergebnis mit /app_dev.php/ gestartet Ergebnis mit /app_dev.php/ gestartet

  2. Ergebnis mit /app.php/ gestartet Ergebnis mit /app.php/ gestartet

  3. Ergebnis mit / gestartet Geben Sie hier die Bildbeschreibung ein

Also ... NUR - Das zweite Bild - Div B - Div C sind die zulässigen Syntaxen.

Hier gibt es den TWIG-Code:

<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>

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

Und a.css, b.css, c.css usw .: alle identisch, nur die Farbe und die CSS-Auswahl ändern.

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

Die Struktur "Verzeichnisse" lautet:

Verzeichnisse Verzeichnisse

All dies kam, weil ich nicht wollte, dass die einzelnen Originaldateien der Öffentlichkeit zugänglich gemacht wurden, insbesondere wenn ich mit "weniger" Filter oder "sass" oder ähnlichem spielen wollte ... Ich wollte nicht, dass meine "Originale" veröffentlicht wurden, sondern nur die einen zusammengestellt.

Aber es gibt gute Nachrichten . Wenn Sie das "Ersatz-CSS" nicht in den öffentlichen Verzeichnissen haben möchten ... installieren Sie sie nicht mit --symlink, sondern erstellen Sie wirklich eine Kopie. Sobald "assetic" das zusammengesetzte CSS erstellt hat, können Sie das ursprüngliche CSS aus dem Dateisystem löschen und die Bilder belassen:

Kompilierungsprozess Kompilierungsprozess

Hinweis Ich mache das für die --env=prodUmwelt.

Nur ein paar abschließende Gedanken:

  • Dieses gewünschte Verhalten kann erreicht werden, indem die Bilder im "öffentlichen" Verzeichnis in Git oder Mercurial und das "CSS" im "Assets" -Verzeichnis gespeichert werden. Das heißt, anstatt sie in "public" zu haben, wie in den Verzeichnissen gezeigt, stellen Sie sich a, b, c ... vor, die sich in den "Assets" statt "public" befinden, als Ihr Installationsprogramm / Deployer (wahrscheinlich ein Bash- Skript). Das CSS vorübergehend in das "öffentliche" Verzeichnis zu stellen, bevor assets:installes ausgeführt wird, dann assets:install, dann assetic:dump, und dann das Entfernen von CSS aus dem öffentlichen Verzeichnis zu automatisieren, nachdem assetic:dumpes ausgeführt wurde. Dies würde genau das in der Frage gewünschte Verhalten erreichen.

  • Eine andere (wenn möglich unbekannte) Lösung wäre zu untersuchen, ob "Assets: Install" nur "public" als Quelle oder "Assets" als Quelle für die Veröffentlichung verwenden kann. Das würde bei der Installation mit der --symlinkOption bei der Entwicklung helfen .

  • Wenn wir das Entfernen aus dem "öffentlichen" Verzeichnis skripten, entfällt außerdem die Notwendigkeit, sie in einem separaten Verzeichnis ("Assets") zu speichern. Sie können in unserem Versionskontrollsystem in "public" leben, da diese bei der Bereitstellung für die Öffentlichkeit gelöscht werden. Dies ermöglicht auch die --symlinkVerwendung.

ABER JEDOCH, VORSICHT JETZT: Wie jetzt sind die Originale nicht mehr da (rm -Rf da sind ), gibt es nur zwei Lösungen, nicht drei. Der Arbeitsbereich "B" funktioniert nicht mehr, da es sich um einen Asset () -Aufruf handelte, sofern der ursprüngliche Asset vorhanden war. Nur "C" (das kompilierte) funktioniert.

Also ... es gibt NUR einen ENDGÜLTIGEN GEWINNER: Div "C" erlaubt genau das, was im Thema gefragt wurde: Um kompiliert zu werden, respektieren Sie den Pfad zu den Bildern und setzen Sie die Originalquelle nicht der Öffentlichkeit aus.

Der Gewinner ist C.

Der Gewinner ist C.

Xavi Montero
quelle
3
Links zu den Bildern für den vorherigen Eintrag: 1) mit /app_dev.php/ gestartet Ergebnis , 2) mit /app.php/ gestartet Ergebnis Link , 3) Ergebnis mit / gestartet Link , 4) Verzeichnisse verknüpfen , 5) Compilation Prozess Link , 6) Wer ist der Gewinner Link
Xavi Montero
1
Und wenn Sie ein Bild aus einem anderen Bundle hinzufügen möchten, anstatt background-image: url('../images/devil.png');dieses zu verwendenbackground-image: url('../../../bundles/frontendlayout/images/devil.png');
Xavi Montero
1
Funktioniert auch mit der Kombination von "cssrewrite" mit "less":{% stylesheets filter="cssrewrite,less" "bundles/frontendlayout/less/layout.less" %} <link href="{{ asset_url }}" rel="stylesheet" type="text/css" /> {% endstylesheets %}
Xavi Montero
1
Dies ist in der Symfony-Dokumentation vermerkt. Siehe hier
Noah Duncan
17

Der cssrewrite-Filter ist derzeit nicht mit der @ bundle-Notation kompatibel. Sie haben also zwei Möglichkeiten:

  • Verweisen Sie auf die CSS - Dateien im Web - Ordner (nach: console assets:install --symlink web)

    {% stylesheets '/bundles/myCompany/css/*." filter="cssrewrite" %}
  • Verwenden Sie den cssembed-Filter, um Bilder wie folgt in das CSS einzubetten.

    {% stylesheets '@MyCompanyMyBundle/Resources/assets/css/*.css' filter="cssembed" %}
jeremymarc
quelle
Danke für deinen Kommentar. Die zweite Lösung klingt ziemlich gut, wenn Sie nur eher kleine Bilder haben. Ich würde mich jedoch nicht wohl fühlen, wenn ich mehr als 100.000 Bilder in die CSS-Datei einfügen würde.
Apfelbox
9

Ich werde dank @ xavi-montero posten, was für mich funktioniert hat.

Legen Sie Ihr CSS in das Resource/public/cssVerzeichnis Ihres Bundles und Ihre Bilder inResource/public/img .

Ändern Sie die assetischen Pfade zum Formular 'bundles/mybundle/css/*.css' in Ihrem Layout.

In config.yml, fügt Regel css_rewritezu assetic:

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

Installieren Sie nun Assets und kompilieren Sie mit assetic:

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

Dies ist gut genug für die Entwicklungsbox und --symlinknützlich, sodass Sie Ihre Assets nicht neu installieren müssen (z. B. fügen Sie ein neues Image hinzu), wenn Sie durch die Box gehenapp_dev.php .

Für den Produktionsserver habe ich gerade die Option '--symlink' (in meinem Bereitstellungsskript) entfernt und diesen Befehl am Ende hinzugefügt:

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

Alles ist getan. Damit können Sie Pfade wie diesen in Ihren CSS-Dateien verwenden:../img/picture.jpeg

ChocoDeveloper
quelle
5

Ich hatte das gleiche Problem und habe nur versucht, Folgendes als Problemumgehung zu verwenden. Scheint soweit zu funktionieren. Sie können sogar eine Dummy-Vorlage erstellen, die nur Verweise auf all diese statischen Assets enthält.

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

Beachten Sie, dass keine Ausgabe vorhanden ist, was bedeutet, dass in der Vorlage nichts angezeigt wird. Wenn ich assetic: dump ausführe, werden die Dateien an den gewünschten Speicherort kopiert und das CSS enthält die erwartete Arbeit.

Cowlby
quelle
1
Sie können einen Konfigurationseintrag für ein benanntes Asset verwenden und müssen ihn nicht in Vorlagen einfügen. Es wird sowieso symfony.com/doc/current/cookbook/assetic/…
venimus
3

Wenn es jemandem helfen kann, haben wir viel mit Assetic zu kämpfen und tun jetzt im Entwicklungsmodus Folgendes:

  • Richten Sie wie in Dumping Asset Files in der Entwicklerumgebung so ein config_dev.yml, dass wir Folgendes kommentiert haben:

    #assetic:
    #    use_controller: true

    Und in routing_dev.yml

    #_assetic:
    #    resource: .
    #    type:     assetic
  • Geben Sie die URL im Webstamm als absolut an. Zum Beispiel Hintergrundbild: url("/bundles/core/dynatree/skins/skin/vline.gif");Hinweis: Unser vhost-Webstamm zeigt auf web/.

  • Keine Verwendung von Cssrewrite-Filter

user1041440
quelle
3
Dies ist eine gültige Lösung, aber nur, wenn Sie die Dateien niemals aus einem Unterverzeichnis bereitstellen, zum Beispiel : http://example.org/sub/.
Apfelbox
1

Ich verwalte das CSS / JS-Plugin mit dem Composer, der es unter dem Hersteller installiert. Ich verknüpfe diese mit dem Verzeichnis web / bundles, damit Composer Bundles nach Bedarf aktualisieren kann.

Beispiel:

1 - Symlink überhaupt einmal verwenden (Befehl fromweb / bundles / verwenden

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

2 - Verwenden Sie das Asset bei Bedarf in einer Zweigvorlage:

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

Grüße.

Jean-Luc Barat
quelle