เส้นทางของเนื้อหาในไฟล์ CSS ใน Symfony 2


101

ปัญหา

ฉันมีไฟล์CSS ที่มีเส้นทางอยู่ในนั้น (สำหรับรูปภาพฟอนต์ ฯลฯ .. url(..))

โครงสร้างเส้นทางของฉันเป็นดังนี้:

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

ฉันต้องการอ้างอิงรูปภาพของฉันในสไตล์ชีต

ทางออกแรก

ฉันเปลี่ยนเส้นทางทั้งหมดในไฟล์ CSS เป็นพา ธ สัมบูรณ์ นี่ไม่ใช่วิธีแก้ปัญหาเนื่องจากแอปพลิเคชันควร (และต้อง!) ทำงานในไดเร็กทอรีย่อยด้วย

แนวทางที่สอง

ใช้ Assetic กับfilter="cssrewrite".

ดังนั้นฉันจึงเปลี่ยนเส้นทางทั้งหมดในไฟล์ CSS เป็น

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

เพื่อแสดงเส้นทางจริงจากไดเร็กทอรีทรัพยากรของฉันไปยัง/web/imagesไดเร็กทอรี สิ่งนี้ใช้ไม่ได้เนื่องจาก cssrewrite สร้างรหัสต่อไปนี้:

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

ซึ่งเห็นได้ชัดว่าเป็นเส้นทางที่ผิด

หลังจากassetic:dumpสร้างเส้นทางนี้แล้วซึ่งยังไม่ถูกต้อง:

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

รหัสกิ่งไม้ของ Assetic:

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

โซลูชันปัจจุบัน (ที่สาม)

เนื่องจากไฟล์ CSS ทั้งหมดลงเอยด้วย/web/css/stylexyz.cssฉันจึงเปลี่ยนเส้นทางทั้งหมดในไฟล์ CSS ให้สัมพันธ์กัน:

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

โซลูชัน (ไม่ดี) นี้ใช้งานได้ยกเว้นในdevสภาพแวดล้อม: พา ธ CSS /app_dev.php/css/stylexyz.cssจึงเป็นพา ธ รูปภาพที่เป็นผลมาจากสิ่งนี้/app_dev.php/images/myimage.pngซึ่งส่งผลให้เกิดNotFoundHttpExceptionไฟล์.

มีวิธีแก้ปัญหาที่ดีกว่าและใช้ได้ผลหรือไม่?


1
ฉันโพสต์วิธีแก้ปัญหาที่นี่: stackoverflow.com/q/9501248/1146363
Cerad

วิธีนี้แก้ปัญหาเส้นทางเมื่อใช้งานได้จริงapp_dev.phpหรือไม่?
apfelbox

คำตอบ:


194

ฉันเจอปัญหาเดียวกันมาก

ในระยะสั้น:

  • ยินดีที่จะมี CSS ดั้งเดิมใน dir "ภายใน" (ทรัพยากร / สินทรัพย์ / css / a.css)
  • ยินดีที่จะมีภาพใน dir "สาธารณะ" (แหล่งข้อมูล / public / images / devil.png)
  • ด้วยความเต็มใจที่จะรับ CSS นั้นมาคอมไพล์ใหม่ในเว็บ / css / a.css และทำให้มันชี้ภาพใน /web/bundles/mynicebundle/images/devil.png

ฉันได้ทำการทดสอบด้วยชุดค่าผสมที่เป็นไปได้ทั้งหมดดังต่อไปนี้:

  • @ หมายเหตุสัญกรณ์สัมพัทธ์
  • แยกวิเคราะห์ด้วย cssrewrite โดยไม่มีมัน
  • พื้นหลังภาพ CSS เทียบกับแท็ก <img> โดยตรง src = เป็นภาพเดียวกันกับ CSS
  • CSS แยกวิเคราะห์ด้วย assetic และยังไม่มีการแยกวิเคราะห์ด้วยเอาต์พุตโดยตรง assetic
  • และทั้งหมดนี้คูณด้วยการลองใช้ "public dir" (as Resources/public/css) กับ CSS และไดเรกทอรี "private" (as Resources/assets/css)

สิ่งนี้ทำให้ฉันมีชุดค่าผสมทั้งหมด 14 ชุดบนกิ่งไม้เดียวกันและเส้นทางนี้เปิดตัวจาก

  • "/app_dev.php/"
  • "/app.php/"
  • และ "/"

จึงให้การทดสอบ 14 x 3 = 42

นอกจากนี้ทั้งหมดนี้ได้รับการทดสอบการทำงานในไดเร็กทอรีย่อยดังนั้นจึงไม่มีทางที่จะหลอกโดยการให้ URL ที่สมบูรณ์เพราะจะไม่ได้ผล

การทดสอบเป็นภาพที่ไม่มีชื่อสองภาพจากนั้นจึงตั้งชื่อ div จาก 'a' ถึง 'f' สำหรับ CSS ที่สร้างจากโฟลเดอร์สาธารณะและตั้งชื่อว่า 'g ถึง' l สำหรับภาพที่สร้างจากเส้นทางภายใน

ฉันสังเกตสิ่งต่อไปนี้:

มีการทดสอบเพียง 3 รายการจากทั้งหมด 14 รายการเท่านั้นที่แสดงอย่างเพียงพอใน URL ทั้งสามรายการ และไม่มีมาจากโฟลเดอร์ "ภายใน" (ทรัพยากร / สินทรัพย์) เป็นข้อกำหนดเบื้องต้นที่จะต้องมี CSS PUBLIC สำรองจากนั้นสร้างด้วย assetic จากที่นั่น

นี่คือผลลัพธ์:

  1. เปิดผลลัพธ์ด้วย /app_dev.php/ เปิดผลลัพธ์ด้วย /app_dev.php/

  2. เปิดผลลัพธ์ด้วย /app.php/ เปิดผลลัพธ์ด้วย /app.php/

  3. เปิดผลลัพธ์ด้วย / ใส่คำอธิบายภาพที่นี่

ดังนั้น ... เท่านั้น - ภาพที่สอง - Div B - Div C เป็นไวยากรณ์ที่อนุญาต

นี่คือรหัส 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;
}

และ a.css, b.css, c.css ฯลฯ : เหมือนกันทั้งหมดเพียงแค่เปลี่ยนสีและตัวเลือก CSS

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

โครงสร้าง "ไดเรกทอรี" คือ:

ไดเรกทอรี ไดเรกทอรี

ทั้งหมดนี้เกิดขึ้นเพราะฉันไม่ต้องการให้ไฟล์ต้นฉบับแต่ละไฟล์เปิดเผยต่อสาธารณะโดยเฉพาะหากฉันต้องการเล่นกับฟิลเตอร์ "น้อย" หรือ "sass" หรือที่คล้ายกัน ... ฉันไม่ต้องการให้ "ต้นฉบับ" ของฉันเผยแพร่เฉพาะ รวบรวมหนึ่ง

แต่มีข่าวดี . หากคุณไม่ต้องการมี "CSS สำรอง" ในไดเรกทอรีสาธารณะ ... อย่าติดตั้งด้วย--symlinkแต่ทำสำเนาจริงๆ เมื่อ "assetic" สร้าง CSS แบบผสมและคุณสามารถลบ CSS ดั้งเดิมออกจากระบบไฟล์และออกจากภาพ:

กระบวนการรวบรวม กระบวนการรวบรวม

หมายเหตุฉันทำสิ่งนี้เพื่อ--env=prodสิ่งแวดล้อม

ความคิดสุดท้ายเพียงไม่กี่:

  • พฤติกรรมที่ต้องการนี้สามารถทำได้โดยการมีรูปภาพในไดเรกทอรี "สาธารณะ" ในGitหรือMercurialและ "css" ในไดเร็กทอรี "assets" นั่นคือแทนที่จะให้พวกเขาอยู่ใน "สาธารณะ" ตามที่แสดงในไดเร็กทอรีให้ลองนึกภาพ a, b, c ... อาศัยอยู่ใน "assets" แทนที่จะเป็น "public" แทนที่จะมีโปรแกรมติดตั้ง / ตัวปรับใช้ของคุณ (อาจเป็นBash script) เพื่อวาง CSS ไว้ใน dir "สาธารณะ" ชั่วคราวก่อนที่assets:installจะดำเนินการจากassets:installนั้นassetic:dumpจากนั้นจึงดำเนินการลบ CSS ออกจากไดเรกทอรีสาธารณะโดยอัตโนมัติหลังจากที่assetic:dumpดำเนินการแล้ว สิ่งนี้จะบรรลุพฤติกรรมที่ต้องการในคำถามอย่างแน่นอน

  • อีกวิธีหนึ่ง (ไม่ทราบว่าเป็นไปได้) คือการสำรวจว่า "สินทรัพย์: ติดตั้ง" สามารถใช้ "สาธารณะ" เป็นแหล่งที่มาเท่านั้นหรืออาจใช้ "เนื้อหา" เป็นแหล่งที่มาเพื่อเผยแพร่ ซึ่งจะช่วยได้เมื่อติดตั้ง--symlinkตัวเลือกเมื่อพัฒนา

  • นอกจากนี้หากเราจะเขียนสคริปต์การลบออกจากผบ. "สาธารณะ" ความจำเป็นในการจัดเก็บไว้ในไดเรกทอรีแยกต่างหาก ("ทรัพย์สิน") จะหายไป พวกเขาสามารถอยู่ภายใน "สาธารณะ" ในระบบควบคุมเวอร์ชันของเราได้เนื่องจากจะถูกทิ้งเมื่อนำไปใช้งานต่อสาธารณะ นี้ยังช่วยให้การ--symlinkใช้งาน

แต่อย่างไรก็ตามข้อควรระวังในตอนนี้:เนื่องจากตอนนี้ต้นฉบับไม่ได้อยู่ที่นั่นอีกต่อไป (rm -Rf ) มีเพียงสองวิธีไม่ใช่สามวิธี div ที่ทำงาน "B" ไม่ทำงานอีกต่อไปเนื่องจากเป็นการเรียกเนื้อหา () โดยสมมติว่ามีเนื้อหาดั้งเดิม เฉพาะ "C" (อันที่คอมไพล์) เท่านั้นที่จะใช้งานได้

ดังนั้น ... มีเพียงผู้ชนะรอบสุดท้ายเท่านั้น: Div "C" อนุญาตให้ตอบคำถามในหัวข้อนี้ได้อย่างถูกต้อง: ในการรวบรวมโปรดเคารพเส้นทางไปยังรูปภาพและอย่าเปิดเผยแหล่งที่มาต้นฉบับต่อสาธารณะ

ผู้ชนะคือ C

ผู้ชนะคือ C


3
ลิงก์ไปยังรูปภาพสำหรับโพสต์ก่อนหน้า: 1) ผลลัพธ์ที่เปิดด้วย /app_dev.php/ , 2) ผลลัพธ์ที่เปิดด้วยลิงก์ /app.php/ , 3) ผลลัพธ์ที่เปิดด้วย / ลิงก์ , 4) ลิงก์ไดเร็กทอรี, 5) ลิงก์กระบวนการคอมไพล์, 6) ลิงค์
Xavi Montero

1
และหากคุณต้องการเพิ่มรูปภาพจากกลุ่มอื่นแทนที่จะใช้ให้background-image: url('../images/devil.png');ใช้สิ่งนี้background-image: url('../../../bundles/frontendlayout/images/devil.png');
Xavi Montero

1
ยังทำงานรวม "cssrewrite" กับ "less":{% stylesheets filter="cssrewrite,less" "bundles/frontendlayout/less/layout.less" %} <link href="{{ asset_url }}" rel="stylesheet" type="text/css" /> {% endstylesheets %}
Xavi Montero

1
สิ่งนี้ระบุไว้ในเอกสารซิมโฟนี ดูที่นี่
Noah Duncan

17

ตัวกรอง cssrewrite ใช้กับสัญกรณ์ @bundle ไม่ได้ในตอนนี้ ดังนั้นคุณมีสองทางเลือก:

  • อ้างอิง CSS ไฟล์ในโฟลเดอร์เว็บ (หลัง: console assets:install --symlink web)

    {% stylesheets '/bundles/myCompany/css/*." filter="cssrewrite" %}
  • ใช้ตัวกรอง cssembed เพื่อฝังรูปภาพใน CSS เช่นนี้

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

ขอบคุณสำหรับความคิดเห็นของคุณ. วิธีที่สองฟังดูดีถ้าคุณมีภาพค่อนข้างเล็ก ฉันไม่สบายใจที่จะใส่รูปภาพ 100k + ในไฟล์ CSS
apfelbox

9

ฉันจะโพสต์สิ่งที่ได้ผลสำหรับฉันขอบคุณ @ xavi-montero

ใส่ CSS ของคุณในห่อของไดเรกทอรีและภาพของคุณในการพูดResource/public/cssResource/public/img

เปลี่ยนเส้นทางการประเมินเป็นแบบฟอร์ม'bundles/mybundle/css/*.css'ในเค้าโครงของคุณ

ในconfig.ymlเพิ่มกฎcss_rewriteในการรับรอง:

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

ตอนนี้ติดตั้งสินทรัพย์และรวบรวมด้วย assetic:

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

สิ่งนี้ดีพอสำหรับกล่องการพัฒนาและ--symlinkมีประโยชน์ดังนั้นคุณจึงไม่ต้องติดตั้งเนื้อหาของคุณใหม่ (เช่นคุณเพิ่มรูปภาพใหม่) เมื่อคุณเข้าสู่app_dev.phpเมื่อคุณป้อนผ่าน

สำหรับเซิร์ฟเวอร์ที่ใช้งานจริงฉันเพิ่งลบอ็อพชัน '--symlink' (ในสคริปต์การปรับใช้ของฉัน) และเพิ่มคำสั่งนี้ในตอนท้าย:

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

ทั้งหมดเสร็จสิ้น ด้วยวิธีนี้คุณสามารถใช้เส้นทางเช่นนี้ในไฟล์. css ของคุณ:../img/picture.jpeg


5

ฉันมีปัญหาเดียวกันและฉันเพิ่งลองใช้สิ่งต่อไปนี้เป็นวิธีแก้ปัญหา ดูเหมือนว่าจะทำงานจนถึงตอนนี้ คุณยังสามารถสร้างเทมเพลตจำลองที่มีการอ้างอิงถึงเนื้อหาคงที่ทั้งหมด

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

สังเกตเห็นการละเว้นเอาต์พุตใด ๆ ซึ่งหมายความว่าไม่มีสิ่งใดปรากฏบนเทมเพลต เมื่อฉันรัน assetic: การถ่ายโอนไฟล์จะถูกคัดลอกไปยังตำแหน่งที่ต้องการและ css รวมถึงการทำงานตามที่คาดไว้


1
คุณสามารถใช้รายการกำหนดค่าสำหรับเนื้อหาที่ระบุชื่อและคุณไม่จำเป็นต้องรวมไว้ในเทมเพลต มันจะทิ้งอะไรก็ได้symfony.com/doc/current/cookbook/assetic/…
venimus

3

หากสามารถช่วยใครสักคนได้เราได้ต่อสู้กับ Assetic มามากและตอนนี้เรากำลังทำสิ่งต่อไปนี้ในโหมดการพัฒนา:

  • ตั้งค่าเหมือนในDumping Asset Files ใน dev Environmenดังนั้นในconfig_dev.ymlเราได้แสดงความคิดเห็น:

    #assetic:
    #    use_controller: true

    และใน Routing_dev.yml

    #_assetic:
    #    resource: .
    #    type:     assetic
  • ระบุ URL เป็นค่าสัมบูรณ์จากเว็บรูท ยกตัวอย่างเช่นภาพพื้นหลัง: url("/bundles/core/dynatree/skins/skin/vline.gif");หมายเหตุ: เว็บราก vhost web/ของเราคือการชี้บน

  • ไม่มีการใช้ตัวกรอง cssrewrite


3
นี่คือวิธีการแก้ปัญหาที่ถูกต้อง http://example.org/sub/แต่ถ้าคุณจะไม่ทำหน้าที่ไฟล์จากไดเรกทอรีย่อยตัวอย่างเช่น:
apfelbox

1

ฉันปิดการจัดการปลั๊กอิน css / js ด้วยนักแต่งเพลงที่ติดตั้งภายใต้ผู้ขาย ฉันเชื่อมโยงสิ่งเหล่านั้นกับไดเร็กทอรีเว็บ / บันเดิลนั่นคือให้ผู้แต่งอัปเดตบันเดิลตามต้องการ

ตัวอย่าง:

1 - symlink ครั้งเดียว (ใช้คำสั่งจากเว็บ / บันเดิล /

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

2 - ใช้เนื้อหาตามความจำเป็นในเทมเพลต Twig:

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

ความนับถือ.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.