web-dev-qa-db-fra.com

Chemin des ressources dans les fichiers CSS dans Symfony 2

Problème

J'ai un fichier CSS avec des chemins d'accès (pour les images, les polices de caractères, etc. url(..)).

Ma structure de chemin est comme ceci:

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

Je veux référencer mes images dans la feuille de style.

Première solution

J'ai changé tous les chemins du fichier CSS en chemins absolus. Ce n'est pas une solution, car l'application doit (et doit!) Fonctionner également dans un sous-répertoire.

Deuxième solution

Utilisez Assetic avec filter="cssrewrite".

J'ai donc changé tous mes chemins dans mon fichier CSS pour

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

pour représenter le chemin actuel de mon répertoire de ressources vers le /web/images répertoire. Cela ne fonctionne pas, car cssrewrite produit le code suivant:

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

ce qui est évidemment le mauvais chemin.

Après assetic:dump ce chemin est créé, ce qui est toujours faux:

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

Le code twig de Assetic:

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

Solution actuelle (troisième)

Comme tous les fichiers CSS finissent dans /web/css/stylexyz.css, J’ai modifié tous les chemins du fichier CSS:

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

Cette (mauvaise) solution fonctionne, sauf dans l’environnement dev: le chemin CSS est /app_dev.php/css/stylexyz.css et donc le chemin de l'image qui en résulte est /app_dev.php/images/myimage.png, ce qui donne NotFoundHttpException.

Y a-t-il une solution meilleure et efficace?

99
apfelbox

Je suis tombé sur le même problème.

En bref:

  • Vouloir avoir le CSS original dans un répertoire "interne" (Ressources/assets/css/a.css)
  • Vouloir avoir les images dans le répertoire "public" (Ressources/public/images/devil.png)
  • En voulant que twig prenne ce CSS, le recompile dans web/css/a.css et le fait pointer l'image dans /web/bundles/mynicebundle/images/devil.png

J'ai effectué un test avec TOUTES les combinaisons possibles (saines) des éléments suivants:

  • @notation, notation relative
  • Analyser avec cssrewrite, sans elle
  • CSS image fond vs direct <img> tag src = à la même image que CSS
  • CSS analysé avec assetic et aussi sans analyse avec la sortie directe assetic
  • Et tout cela multiplié en essayant un "public dir" (comme Resources/public/css) avec le CSS et un répertoire "privé" (comme Resources/assets/css).

Cela m'a donné un total de 14 combinaisons sur la même branche, et cette route a été lancée à partir de

  • "/app_dev.php/"
  • "/app.php/"
  • et "/"

donnant ainsi 14 x 3 = 42 tests.

En outre, tout cela a été testé dans un sous-répertoire. Il n’ya donc aucun moyen de tromper en donnant des URL absolues car elles ne fonctionneraient tout simplement pas.

Les tests consistaient en deux images sans nom, puis en divs nommés de 'a' à 'f' pour le CSS construit à partir du dossier public et nommés 'g à' l 'pour ceux construits à partir du chemin interne.

J'ai observé ce qui suit:

Seuls 3 des 14 tests ont été présentés de manière adéquate sur les trois URL. Et NONE provenait du dossier "interne" (Ressources/actifs). C'était une condition préalable pour disposer de la réserve CSS PUBLIC, puis compiler avec assetic à partir de là.

Ce sont les résultats:

  1. Résultat lancé avec /app_dev.php/ Result launched with /app_dev.php/

  2. Résultat lancé avec /app.php/ Result launched with /app.php/

  3. Résultat lancé avec / enter image description here

Alors ... SEULEMENT - La deuxième image - Div B - Div C sont les syntaxes autorisées.

Voici le code 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>

Le conteneur.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;
}

Et a.css, b.css, c.css, etc.: tous identiques, il suffit de changer la couleur et le sélecteur CSS.

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

La structure "répertoires" est:

Répertoires Directories

Tout cela est arrivé, parce que je ne voulais pas que les fichiers originaux individuels soient exposés au public, surtout si je voulais jouer avec "moins" filtre ou "sass" ou similaire ... Je n'ai pas voulu veux que mes "originaux" soient publiés, seulement celui qui a été compilé.

Mais il y a de bonnes nouvelles . Si vous ne voulez pas avoir le "CSS de réserve" dans les répertoires publics ... ne les installez pas avec --symlink, mais en fait vraiment une copie. Une fois que "assetic" a construit le CSS composé, vous pouvez supprimer le CSS original du système de fichiers et laisser les images:

Processus de compilation Compilation process

Notez que je fais cela pour le --env=prod environnement.

Juste quelques réflexions finales:

  • Ce comportement souhaité peut être obtenu en ayant les images dans le répertoire "public" de Git ou Mercurial et le "css" dans le répertoire "assets". C’est-à-dire qu’au lieu de les avoir "publics" comme indiqué dans les répertoires, imaginez a, b, c ... résidant dans les "actifs" au lieu de "public", plutôt que votre installateur/déployeur (probablement un Bash script) pour mettre le CSS temporairement dans le répertoire "public" avant le assets:install est exécuté, puis assets:install, puis assetic:dump, puis automatiser la suppression de CSS du répertoire public après assetic:dump a été exécuté. Cela permettrait d'atteindre EXACTEMENT le comportement souhaité dans la question.

  • Une autre solution (inconnue si possible) serait d'explorer si "assets: install" ne peut prendre que "public" en tant que source ou pourrait également prendre des "assets" comme source à publier. Cela aiderait une fois installé avec le --symlink option lors du développement.

  • De plus, si nous allons écrire la suppression du répertoire "public" dans un script, la nécessité de les stocker dans un répertoire séparé ("assets") disparaît. Ils peuvent vivre dans un environnement "public" dans notre système de contrôle de version, car ils seront abandonnés lors du déploiement au public. Cela permet aussi pour le --symlink utilisation.

MAIS TOUJOURS, ATTENTION MAINTENANT: Comme maintenant les originaux ne sont plus là (rm -Rf), il n’ya que deux solutions, pas trois. La division de travail "B" ne fonctionne plus car il s'agissait d'un appel à asset () en supposant qu'il y avait l'actif d'origine. Seul "C" (celui compilé) fonctionnera.

Donc ... il n'y a QU'UN SEUL GAGNANT FINAL: Div "C" permet EXACTEMENT ce qu'il a été demandé dans le sujet: Pour être compilé, respectez le chemin d'accès aux images et n'exposez pas la source originale au public.

Le gagnant est C

The winner is C

193
Xavi Montero

Le filtre cssrewrite n'est pas compatible avec la notation @bundle pour l'instant. Donc vous avez deux choix:

  • Référencez les fichiers CSS dans le dossier Web (après: console assets:install --symlink web)

    {% stylesheets '/bundles/myCompany/css/*." filter="cssrewrite" %}
    
  • Utilisez le filtre cssembed pour incorporer des images dans le CSS comme ceci.

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

Je posterai ce qui a fonctionné pour moi, grâce à @ xavi-montero.

Mettez votre CSS dans votre paquet Resource/public/css répertoire, et vos images disons Resource/public/img.

Changer les chemins assoits à la forme 'bundles/mybundle/css/*.css', dans votre mise en page.

Dans config.yml, ajouter la règle css_rewrite à assetic:

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

Maintenant, installez les ressources et compilez avec assetic:

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

C'est assez bon pour la boite de développement, et --symlink est utile, il n’est donc pas nécessaire de réinstaller vos actifs (par exemple, vous ajoutez une nouvelle image) lorsque vous entrez par app_dev.php.

Pour le serveur de production, je viens de supprimer l'option '--symlink' (dans mon script de déploiement), et j'ai ajouté cette commande à la fin:

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

Tout est fait. Avec cela, vous pouvez utiliser des chemins comme celui-ci dans vos fichiers .css: ../img/picture.jpeg

8
ChocoDeveloper

J'ai eu le même problème et j'ai juste essayé d'utiliser ce qui suit comme solution de contournement. Semble travailler jusqu'à présent. Vous pouvez même créer un modèle factice contenant uniquement des références à tous ces actifs statiques.

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

Notez l'omission de toute sortie, ce qui signifie que rien ne s'affiche sur le modèle. Quand j'exécute assetic: dump, les fichiers sont copiés à l'emplacement souhaité et les fichiers css fonctionnent comme prévu.

5
Cowlby

Si cela peut aider quelqu'un, nous avons beaucoup lutté avec Assetic, et nous procédons maintenant comme suit en mode de développement:

  • Configuré comme dans Dumping des fichiers d'actifs dans l'environnement de développement, de sorte que dans config_dev.yml, Nous avons commenté:

    #assetic:
    #    use_controller: true
    

    Et dans routing_dev.yml

    #_assetic:
    #    resource: .
    #    type:     assetic
    
  • Spécifiez l'URL comme absolue à partir de la racine Web. Par exemple, image d’arrière-plan: url("/bundles/core/dynatree/skins/skin/vline.gif"); Remarque: notre racine Web vhost pointe sur web/.

  • Pas d'utilisation du filtre cssrewrite

2
user1041440

Je gère souvent le plug-in css/js avec composer qui l'installe sous l'éditeur. Je lie ces liens vers le répertoire web/bundles, c'est-à-dire composer met à jour les ensembles au besoin). .

exemple:

1 - lien symbolique une seule fois (utilisez la commande fromweb/bundles /

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

2 - utilisez l'actif si nécessaire, dans twig template:

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

Cordialement.

1
Jean-Luc Barat