Jalur aset dalam file CSS di Symfony 2

101

Masalah

Saya memiliki file CSS dengan beberapa jalur di dalamnya (untuk gambar, font, dll .. url(..)).

Struktur jalur saya seperti ini:

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

Saya ingin mereferensikan gambar saya di stylesheet.

Solusi Pertama

Saya mengubah semua jalur di file CSS menjadi jalur absolut. Ini bukan solusi, karena aplikasi harus (dan harus!) Bekerja di subdirektori juga.

Solusi Kedua

Gunakan Assetic dengan filter="cssrewrite".

Jadi saya mengubah semua jalur saya di file CSS saya menjadi

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

untuk mewakili jalur sebenarnya dari direktori resource saya ke /web/imagesdirektori. Ini tidak berfungsi, karena cssrewrite menghasilkan kode berikut:

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

yang jelas merupakan jalan yang salah.

Setelah assetic:dumpjalur ini dibuat, yang masih salah:

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

Kode ranting Assetic:

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

Solusi Saat Ini (Ketiga)

Karena semua file CSS berakhir /web/css/stylexyz.css, saya mengubah semua jalur di file CSS menjadi relatif:

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

Solusi (buruk) ini berfungsi, kecuali di devlingkungan: Jalur CSS adalah /app_dev.php/css/stylexyz.cssdan oleh karena itu jalur gambar yang dihasilkan /app_dev.php/images/myimage.pngdarinya, yang menghasilkan file NotFoundHttpException.

Apakah ada solusi yang lebih baik dan berhasil?

apfelbox
sumber
1
Saya memposting solusi saya di sini: stackoverflow.com/q/9501248/1146363
Cerad
Apakah ini benar-benar menyelesaikan masalah dengan jalur saat menggunakan app_dev.php?
apfelbox

Jawaban:

194

Saya telah menemukan masalah yang sama.

Pendeknya:

  • Bersedia memiliki CSS asli di direktori "internal" (Resources / assets / css / a.css)
  • Bersedia untuk memiliki gambar di direktori "publik" (Resources / public / images / devil.png)
  • Bersedia ranting itu mengambil CSS itu, mengkompilasinya kembali ke web / css / a.css dan membuatnya mengarahkan gambar ke /web/bundles/mynicebundle/images/devil.png

Saya telah menguji SEMUA kemungkinan kombinasi (waras) berikut ini:

  • @notasi, notasi relatif
  • Parse dengan cssrewrite, tanpa itu
  • Latar belakang gambar CSS vs <img> tag src = langsung ke gambar yang sama dengan CSS
  • CSS diurai dengan assetic dan juga tanpa parsing dengan output langsung assetic
  • Dan semua ini dikalikan dengan mencoba "public dir" (as Resources/public/css) dengan CSS dan direktori "private" (as Resources/assets/css).

Ini memberi saya total 14 kombinasi pada ranting yang sama, dan rute ini diluncurkan dari

  • "/app_dev.php/"
  • "/app.php/"
  • dan "/"

sehingga memberikan 14 x 3 = 42 tes.

Selain itu, semua ini telah diuji bekerja di subdirektori, jadi tidak ada cara untuk menipu dengan memberikan URL absolut karena mereka tidak akan berfungsi.

Tesnya adalah dua gambar tanpa nama dan kemudian div dinamai dari 'a' hingga 'f' untuk CSS yang dibangun DARI folder publik dan diberi nama 'g ke' l 'untuk yang dibangun dari jalur internal.

Saya mengamati yang berikut:

Hanya 3 dari 14 pengujian yang ditampilkan secara memadai pada tiga URL. Dan TIDAK ADA dari folder "internal" (Sumber Daya / aset). Itu adalah prasyarat untuk memiliki cadangan CSS PUBLIK dan kemudian membangun dengan aset dari sana.

Inilah hasilnya:

  1. Hasil diluncurkan dengan /app_dev.php/ Hasil diluncurkan dengan /app_dev.php/

  2. Hasil diluncurkan dengan /app.php/ Hasil diluncurkan dengan /app.php/

  3. Hasil diluncurkan dengan / masukkan deskripsi gambar di sini

Jadi ... HANYA - Gambar kedua - Div B - Div C adalah sintaks yang diizinkan.

Di sini ada kode 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;
}

Dan a.css, b.css, c.css, dll: semuanya identik, hanya mengubah warna dan pemilih CSS.

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

Struktur "direktori" adalah:

Direktori Direktori

Semua ini datang, karena saya tidak ingin file asli individu diekspos ke publik, khususnya jika saya ingin bermain dengan filter "kurang" atau "sass" atau serupa ... Saya tidak ingin "aslinya" dipublikasikan, hanya menyusun satu.

Tapi ada kabar baik . Jika Anda tidak ingin memiliki "CSS cadangan" di direktori publik ... jangan instal dengan --symlink, tetapi benar-benar membuat salinan. Setelah "assetic" membuat CSS gabungan, dan Anda dapat MENGHAPUS CSS asli dari sistem file, dan meninggalkan gambar:

Proses kompilasi Proses kompilasi

Catatan Saya melakukan ini untuk --env=prodlingkungan.

Hanya beberapa pemikiran terakhir:

  • Perilaku yang diinginkan ini dapat dicapai dengan memiliki gambar di direktori "publik" di Git atau Mercurial dan "css" di direktori "aset". Artinya, alih-alih menyimpannya di "publik" seperti yang ditunjukkan di direktori, bayangkan a, b, c ... berada di "aset" alih-alih "publik", daripada memiliki penginstal / penerapan Anda (mungkin skrip Bash ) untuk meletakkan CSS sementara di dalam direktori "public" sebelum assets:installdijalankan, lalu assets:install, kemudian assetic:dump, dan kemudian secara otomatis menghapus CSS dari direktori publik setelah assetic:dumpdijalankan. Ini akan mencapai PERSIS perilaku yang diinginkan dalam pertanyaan itu.

  • Solusi lain (tidak diketahui jika memungkinkan) adalah menyelidiki apakah "assets: install" hanya dapat mengambil "publik" sebagai sumber atau juga dapat mengambil "aset" sebagai sumber untuk dipublikasikan. Itu akan membantu saat dipasang dengan --symlinkopsi saat mengembangkan.

  • Selain itu, jika kita akan membuat skrip penghapusan dari direktori "public", maka kebutuhan untuk menyimpannya dalam direktori terpisah ("assets") menghilang. Mereka dapat hidup di dalam "publik" dalam sistem kontrol versi kami karena akan dibuang saat diterapkan ke publik. Ini memungkinkan juga untuk --symlinkpenggunaan.

NAMUN, HATI-HATI SEKARANG: Karena sekarang yang asli sudah tidak ada lagi ( rm -Rf), hanya ada dua solusi, bukan tiga. Div yang berfungsi "B" tidak berfungsi lagi karena itu adalah panggilan aset () dengan asumsi ada aset asli. Hanya "C" (yang telah dikompilasi) yang akan bekerja.

Jadi ... HANYA ada PEMENANG AKHIR: Div "C" memungkinkan PERSIS apa yang diminta dalam topik: Untuk dikompilasi, hormati jalur ke gambar dan jangan paparkan sumber aslinya ke publik.

Pemenangnya adalah C

Pemenangnya adalah C

Xavi Montero
sumber
3
Tautan ke gambar untuk posting sebelumnya: 1) Hasil diluncurkan dengan /app_dev.php/ , 2) Hasil diluncurkan dengan /app.php/ link , 3) hasil diluncurkan dengan / link , 4) Tautan direktori , 5) Tautan proses kompilasi , 6) Siapa link
Xavi Montero
1
Dan jika Anda ingin menambahkan gambar dari bundel lain, daripada menggunakan background-image: url('../images/devil.png');inibackground-image: url('../../../bundles/frontendlayout/images/devil.png');
Xavi Montero
1
Juga bekerja menggabungkan "cssrewrite" dengan "less":{% stylesheets filter="cssrewrite,less" "bundles/frontendlayout/less/layout.less" %} <link href="{{ asset_url }}" rel="stylesheet" type="text/css" /> {% endstylesheets %}
Xavi Montero
1
Ini dicatat dalam dokumentasi symfony. Lihat di sini
Noah Duncan
17

Filter cssrewrite tidak kompatibel dengan notasi @bundle untuk saat ini. Jadi, Anda punya dua pilihan:

  • Referensi file CSS di folder web (setelah console assets:install --symlink web:)

    {% stylesheets '/bundles/myCompany/css/*." filter="cssrewrite" %}
  • Gunakan filter cssembed untuk menyematkan gambar di CSS seperti ini.

    {% stylesheets '@MyCompanyMyBundle/Resources/assets/css/*.css' filter="cssembed" %}
jeremymarc
sumber
Terima kasih atas komentarmu. Solusi kedua terdengar cukup bagus jika Anda hanya memiliki gambar yang agak kecil. Saya tidak akan merasa nyaman untuk meletakkan lebih dari 100k + gambar di file CSS.
apfelbox
9

Saya akan memposting apa yang berhasil untuk saya, terima kasih kepada @ xavi-montero.

Letakkan CSS Anda di Resource/public/cssdirektori bundel Anda , dan gambar Anda di katakan Resource/public/img.

Ubah jalur aset ke formulir 'bundles/mybundle/css/*.css', di tata letak Anda.

Di config.yml, tambahkan aturan css_rewriteke assetic:

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

Sekarang instal aset dan kompilasi dengan assetic:

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

Ini cukup baik untuk kotak pengembangan, dan --symlinkberguna, jadi Anda tidak perlu menginstal ulang aset Anda (misalnya, Anda menambahkan gambar baru) saat Anda masuk app_dev.php.

Untuk server produksi, saya baru saja menghapus opsi '--symlink' (dalam skrip penerapan saya), dan menambahkan perintah ini di akhir:

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

Semua sudah selesai. Dengan ini, Anda dapat menggunakan jalur seperti ini di file .css Anda:../img/picture.jpeg

ChocoDeveloper
sumber
5

Saya memiliki masalah yang sama dan saya hanya mencoba menggunakan yang berikut ini sebagai solusi. Sepertinya bekerja sejauh ini. Anda bahkan dapat membuat template tiruan yang hanya berisi referensi ke semua aset statis tersebut.

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

Perhatikan kelalaian output apa pun yang berarti tidak ada yang muncul di template. Ketika saya menjalankan assetic: dump file akan disalin ke lokasi yang diinginkan dan css menyertakan pekerjaan seperti yang diharapkan.

Cowlby
sumber
1
Anda dapat menggunakan entri konfigurasi untuk aset bernama dan Anda tidak perlu memasukkannya ke dalam template. Ini akan membuangnya symfony.com/doc/current/cookbook/assetic/…
venimus
3

Jika itu dapat membantu seseorang, kami telah berjuang keras dengan Assetic, dan kami sekarang melakukan hal berikut dalam mode pengembangan:

  • Siapkan seperti di Dumping Asset Files di dev Environmen jadi di config_dev.yml, kami telah berkomentar:

    #assetic:
    #    use_controller: true

    Dan di routing_dev.yml

    #_assetic:
    #    resource: .
    #    type:     assetic
  • Tentukan URL sebagai absolut dari root web. Misalnya, gambar latar belakang: url("/bundles/core/dynatree/skins/skin/vline.gif");Catatan: root web vhost kami mengarah ke web/.

  • Tidak ada penggunaan filter cssrewrite

pengguna1041440
sumber
3
Ini adalah solusi yang valid, tetapi hanya jika Anda tidak pernah akan melayani file dari subdirektori, misalnya: http://example.org/sub/.
apfelbox
1

Saya tidak suka mengelola plugin css / js dengan komposer yang menginstalnya di bawah vendor. Saya menghubungkannya ke direktori web / bundles, yang memungkinkan komposer memperbarui bundel sesuai kebutuhan.

contoh:

1 - symlink sekali saja (gunakan perintah fromweb / bundles /

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

2 - gunakan aset jika diperlukan, dalam templat ranting:

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

Salam.

Jean-Luc Barat
sumber