Chemin des actifs dans les fichiers CSS dans Symfony 2

101

Problème

J'ai un fichier CSS avec quelques chemins (pour les images, les polices, etc. url(..)).

Ma structure de chemin est comme ceci:

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

Je souhaite 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 devrait (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 en

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

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

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

ce qui est évidemment le mauvais chemin.

Une fois assetic:dumpce chemin créé, ce qui est toujours faux:

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

Le code brindille d'Assetic:

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

Solution actuelle (troisième)

Étant donné que tous les fichiers CSS aboutissent /web/css/stylexyz.css, j'ai changé tous les chemins du fichier CSS pour qu'ils soient relatifs:

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

Cette (mauvaise) solution fonctionne, sauf dans l' devenvironnement: le chemin CSS est /app_dev.php/css/stylexyz.csset donc le chemin de l'image qui en résulte est /app_dev.php/images/myimage.png, ce qui entraîne un NotFoundHttpException.

Existe-t-il une solution meilleure et efficace?

apfelbox
la source
1
J'ai posté ma solution ici: stackoverflow.com/q/9501248/1146363
Cerad
Cela résout-il réellement le problème avec les chemins lors de l'utilisation app_dev.php?
apfelbox

Réponses:

194

J'ai rencontré le même problème.

En bref:

  • Désireux d'avoir le CSS original dans un répertoire "interne" (Resources / assets / css / a.css)
  • Désireux d'avoir les images dans le répertoire "public" (Resources / public / images / devil.png)
  • Vouloir que cette brindille prenne ce CSS, le recompile dans web / css / a.css et lui fait pointer l'image dans /web/bundles/mynicebundle/images/devil.png

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

  • @notation, notation relative
  • Analyser avec cssrewrite, sans lui
  • Arrière-plan de l'image CSS vs balise directe <img> src = vers 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 Resources/public/css"répertoire public" (as ) avec le CSS et un répertoire "privé" (as Resources/assets/css).

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

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

donnant ainsi 14 x 3 = 42 tests.

De plus, tout cela a été testé en travaillant dans un sous-répertoire, il n'y a donc aucun moyen de tromper en donnant des URL absolues car elles ne fonctionneraient tout simplement pas.

Les tests étaient deux images sans nom, puis des 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é montré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 avoir le CSS PUBLIC de rechange et ensuite construire avec assetic FROM là-bas.

Voici les résultats:

  1. Résultat lancé avec /app_dev.php/ Résultat lancé avec /app_dev.php/

  2. Résultat lancé avec /app.php/ Résultat lancé avec /app.php/

  3. Résultat lancé avec / entrez la description de l'image ici

Alors ... UNIQUEMENT - 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 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;
}

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 Répertoires

Tout cela est venu, parce que je ne voulais pas que les fichiers originaux individuels soient exposés au public, spécialement si je voulais jouer avec "moins" filtre ou "sass" ou similaire ... Je ne voulais pas que mes "originaux" soient publiés, seulement le compilé un.

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

Processus de compilation Processus de compilation

Notez que je fais cela pour l' --env=prodenvironnement.

Quelques réflexions finales:

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

  • Une autre solution (inconnue si possible) serait d'explorer si «assets: install» ne peut prendre que «public» comme source ou pourrait également prendre «assets» comme source de publication. Cela aiderait une fois installé avec l' --symlinkoption lors du développement.

  • De plus, si nous allons programmer la suppression du répertoire "public", alors le besoin de les stocker dans un répertoire séparé ("assets") disparaît. Ils peuvent vivre à l'intérieur du "public" dans notre système de contrôle de version, car ils seront supprimés lors du déploiement au public. Cela permet également l' --symlinkutilisation.

MAIS DE TOUTE FAÇON, ATTENTION MAINTENANT: Comme maintenant les originaux ne sont plus là ( rm -Rf), il n'y a 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 y a UNIQUEMENT UN GAGNANT FINAL: la Div "C" permet EXACTEMENT ce qui était 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

Le gagnant est C

Xavi Montero
la source
3
Liens vers les images de l'article précédent: 1) Résultat lancé avec /app_dev.php/ , 2) Résultat lancé avec /app.php/ link , 3) résultat lancé avec / link , 4) Lien vers les répertoires , 5) Lien vers le processus de compilation , 6) Qui est le lien
Xavi Montero
1
Et si vous souhaitez ajouter une image d'un autre ensemble, au lieu d'utiliser, background-image: url('../images/devil.png');utilisez cecibackground-image: url('../../../bundles/frontendlayout/images/devil.png');
Xavi Montero
1
Fonctionne également en combinant "cssrewrite" avec "less":{% stylesheets filter="cssrewrite,less" "bundles/frontendlayout/less/layout.less" %} <link href="{{ asset_url }}" rel="stylesheet" type="text/css" /> {% endstylesheets %}
Xavi Montero
1
Ceci est noté dans la documentation de symfony. Voir ici
Noah Duncan
17

Le filtre cssrewrite n'est pas compatible avec la notation @bundle pour le moment. Vous avez donc deux choix:

  • Référence 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" %}
Jeremymarc
la source
Merci pour votre commentaire. La deuxième solution semble assez bonne si vous n'avez que des images plutôt petites. Cependant, je ne me sentirais pas à l'aise de mettre plus de 100 000 images dans le fichier CSS.
apfelbox
9

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

Mettez votre CSS dans le Resource/public/cssrépertoire de votre bundle , et vos images par exemple Resource/public/img.

Changez les chemins assétiques vers le formulaire 'bundles/mybundle/css/*.css', dans votre mise en page.

Dans config.yml, ajoutez une règle css_rewriteà assetic:

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

Maintenant, installez les actifs 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 boîte de développement et --symlinkutile, vous n'avez donc pas à réinstaller vos actifs (par exemple, vous ajoutez une nouvelle image) lorsque vous entrez 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

ChocoDeveloper
la source
5

J'ai eu le même problème et j'ai juste essayé d'utiliser ce qui suit comme solution de contournement. Semble fonctionner 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 n'apparaît sur le modèle. Lorsque j'exécute assetic: dump, les fichiers sont copiés à l'emplacement souhaité et le css inclut le travail comme prévu.

Cowlby
la source
1
Vous pouvez utiliser une entrée de configuration pour l'actif nommé et vous n'êtes pas obligé de l'inclure dans les modèles. Il videra de
venimus
3

Si cela peut aider quelqu'un, nous avons beaucoup lutté avec Assetic, et nous faisons maintenant ce qui suit en mode développement:

  • Configuré comme dans Dumping Asset Files dans les environnements de développement 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, background-image: url("/bundles/core/dynatree/skins/skin/vline.gif");Remarque: notre racine Web vhost pointe sur web/.

  • Aucune utilisation du filtre cssrewrite

utilisateur1041440
la source
3
Ceci est une solution valable, mais seulement si vous ne servira jamais les fichiers à partir d' un sous - répertoire, par exemple: http://example.org/sub/.
apfelbox
1

Je gère offen css / js plugin avec composer qui l'installe sous le vendeur. Je les lie symboliquement au répertoire web / bundles, ce qui permet au compositeur de mettre à jour les bundles si nécessaire.

exemple:

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

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

2 - utilisez l'actif si nécessaire, dans le modèle de brindille:

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

Cordialement.

Jean-Luc Barat
la source