การตั้งค่าองค์ประกอบของอาร์เรย์จาก Twig


126

ฉันจะตั้งค่าสมาชิกของอาร์เรย์ที่มีอยู่แล้วจาก Twig ได้อย่างไร?

ฉันลองทำวิธีต่อไป:

{% set arr['element'] = 'value' %}

แต่ฉันได้รับข้อผิดพลาดต่อไปนี้:

โทเค็นที่ไม่คาดคิด "เครื่องหมายวรรคตอน" ของค่า "[" (คาดว่าจะเป็น "end of statement block") ใน ...

คำตอบ:


211

ไม่มีวิธีที่ดีในการทำสิ่งนี้ใน Twig อย่างไรก็ตามเป็นไปได้โดยใช้ตัวกรองการผสาน:

{% set arr = arr|merge({'element': 'value'}) %}

"." - คำสั่งเหมือนกับ "[]" ดังนั้นจึงไม่ใช่วิธีแก้ปัญหา
falinsky

@falinsky คุณพูดถูก .และ[]มีความคล้ายคลึงกันมากใน Twig และฉันคิดผิด ฉันมองขึ้นไปและแก้ไขคำตอบของฉัน
Paul

17
ฉันกำลังมองหาวิธีกำหนดคีย์ตัวแปรแบบไดนามิกเพื่อแทนที่'element'. ฉันพบคำตอบของ @ LivaX ด้านล่าง {% set arr = arr|merge({(key): 'value'}) %}ดังนั้นมันจะเป็น
Sithu

นี่มันโง่มาก เหตุใด Twig จึงไม่อนุญาตให้ตั้งค่าอาร์เรย์ได้
Matt Cavanagh

1
@MattCavanagh เนื่องจากไฟล์ดู (เช่น Twig) ไม่ควรมีตรรกะทางธุรกิจในที่สุดสิ่งนี้ควรได้รับการจัดการในแบบจำลอง มุมมองควรจะแสดงสิ่งที่อยู่ตรงนั้นจริงๆ ปัญหาแม้ว่าในกรณีของฉันและทำไมฉันถึงเห็นด้วยกับคุณคือฉันสร้างมาโครกิ่งไม้เพื่อแสดงวัตถุ UI เช่น {{ UI.button({'type':'submit'}) }}และมาโครทั้งหมดเหล่านี้ใช้ | ผสานสำหรับการตั้งค่าพารามิเตอร์เริ่มต้นดังนั้นจึงมีความจำเป็นเชิงตรรกะสำหรับสิ่งนี้ ...
Prof83

80

ฉันพบปัญหานี้ แต่กำลังพยายามสร้างดัชนีจำนวนเต็มแทนที่จะเป็นดัชนีที่เชื่อมโยงเช่น 'องค์ประกอบ'

คุณต้องปกป้องคีย์ดัชนีของคุณด้วยการ()ใช้ตัวกรองผสานเช่นกัน:

{% set arr = arr|merge({ (loop.index0): 'value'}) %} 

ตอนนี้คุณสามารถเพิ่มคีย์ดัชนีที่กำหนดเองเช่น ('element'~loop.index0)


นั่นคือทางออกที่แท้จริงเมื่อคุณพยายามใส่คีย์แบบไดนามิกขอบคุณ LivaX!
nicolallias


2

ฉันได้ลองคำตอบของ @LivaX แล้ว แต่ไม่ได้ผลการรวมอาร์เรย์ที่คีย์เป็นตัวเลขจะไม่ทำงาน ( https://github.com/twigphp/Twig/issues/789 )

ซึ่งจะใช้ได้เฉพาะเมื่อคีย์เป็นสตริง

สิ่งที่ฉันทำคือสร้างตารางอื่น ( temp) จากตารางเริ่มต้น ( t) และทำให้คีย์เป็นสตริงตัวอย่างเช่น:

{% for key , value in t%}
{% set temp= temp|merge({(key~'_'):value}) %}
{% endfor %}

t คีย์: 0, 1, 2 ..

temp คีย์: 0_, 1_, 2_ ....


ปัญหาเดียวกันยังไม่มีวิธีแก้ไข
TyrionGraphiste

2
{% set links = {} %}

{# Use our array to wrap up our links. #}
{% for item in items %}
  {% set links = links|merge({ (loop.index0) : {'url': item.content['#url'].getUri(), 'text': item.content['#title']} }) %}
{% endfor %}

{%
set linkList = {
  'title': label,
  'links': links
}
%}

{% include '<to twig file>/link-list.twig'%}

ขอบคุณสำหรับหัวข้อนี้ - ฉันยังสามารถสร้างอาร์เรย์ด้วย (loop.index0) และส่งไปที่ twig


1

ฉันพบว่าปัญหานี้น่ารำคาญมากและวิธีแก้ปัญหาของฉันอาจเป็นแบบดั้งเดิมและไม่สอดคล้องกับปรัชญาทวิก แต่ฉันได้พัฒนาสิ่งต่อไปนี้:

$function = new Twig_Function('set_element', function ($data, $key, $value) {
    // Assign value to $data[$key]
    if (!is_array($data)) {
        return $data;
    }
    $data[$key] = $value;
    return $data;
});
$twig->addFunction($function);

ที่สามารถใช้ได้ดังต่อไปนี้:

{% set arr = set_element (arr, 'element', 'value')%}


1

เพียงใช้สิ่งนี้{% set arr={'key':'value'} %}(โดยไม่มีช่องว่างหลัง:) ก็ใช้งานได้ดี

แต่เมื่อฉันใช้มันภายใน for loop เพื่อทำให้เป็นอาร์เรย์มันจะไม่ทำงานนอกขอบเขตสำหรับ

{% for group in user.groups %}
  {% set foo={'loop.index0':'group.id'} %}
  {% set title={'loop.index0':'group.title'} %}
  {{ title }} //it work 
{% else %}
  {% set foo={'0':'-1'} %}
  {% set title={'0':'未分组'} %}
{% endfor %}
{{ title }}  //it does not work, saying title is not defined

1
หากคุณต้องการใช้ตัวแปรนอก for loop คุณต้องกำหนดตัวแปรนอก for loop ดูที่นี่: twig.sensiolabs.org/doc/tags/set.html
user2019515

5
นี่คือความผิดทุกประเภท ช่องว่างหลังลำไส้ใหญ่ไม่สำคัญ คุณกำลังสร้างอาร์เรย์ใหม่โดยไม่ได้ตั้งค่าองค์ประกอบในอาร์เรย์ซึ่งเป็นคำถาม คุณไม่สามารถส่งออกอาร์เรย์เช่น {{array}} ได้ซึ่งจะทำให้เกิดข้อผิดพลาด คำตอบนี้เต็มไปด้วยความล้มเหลวและไม่เกี่ยวข้องกับคำถามที่ถาม
จอดรถใหม่

3
ฉันไม่เข้าใจว่าเหตุใดจึงมีการโหวตเพิ่มขึ้นอย่างที่ระบุไว้ข้างต้นเกือบทุกอย่างไม่ถูกต้องใน "คำตอบ" นี้ ...
MariusJP

0

ฉันมีอาร์เรย์หลายมิติ ทางออกเดียวที่ฉันสามารถหาได้คือสร้างอาร์เรย์ชั่วคราวใหม่และอัปเดต / เพิ่มข้อมูลซึ่งส่งต่อไปยังฟังก์ชัน twig อื่น


0

ฉันมีปัญหานี้เมื่อไม่นานมานี้ ลองนึกภาพคุณมีอาร์เรย์เช่นนี้:

data = {
    'user': 'admin',
    'password': 'admin1234',
    'role': 'admin',
    'group': 'root',
    'profile': 'admin',
    'control': 'all',
    'level': 1,
    'session': '#DFSFASADASD02',
    'pre_oa': 'PRE-OA',
    'hepa_oa': 'HEPA-OA',
    'pre_ra': 'HEPA-RA',
    'hepa_ra': 'HEPA-RA',
    'deodor_ra': 'DEODOR-RA'
}

ดังนั้นคุณต้องการแสดงข้อมูลนี้เป็นสองแถว แต่ลบรหัสผ่านออกจากรายการนั้น ด้วยเหตุนี้การแบ่ง 2 อาร์เรย์จะเป็นเรื่องง่ายด้วยsliceตัวกรอง อย่างไรก็ตามเราต้องลบรหัสผ่าน ด้วยเหตุนี้ฉันจึงใช้ตัวอย่างข้อมูลนี้ ความคิดที่จะนำองค์ประกอบทั้งหมดน้อยกว่าdataขนาดองค์ประกอบหารด้วย 2. lengthการคำนวณนี้เราใช้ตัวกรอง loop.indexตอนนี้ที่จะได้รับดัชนีของผู้ใช้องค์ประกอบเราในปัจจุบัน และในที่สุดเราก็ * พุชองค์ประกอบที่เชื่อมโยงในอาร์เรย์ซ้ายหรือขวา อาร์เรย์ที่เชื่อมโยงมีสององค์ประกอบkeyและvalue. ในการอ้างอิงคีย์อาร์เรย์ในตัวดำเนินการ twit เรา()และเราใช้mergeตัวกรองเพื่อดันเข้าไปในอาร์เรย์ดังที่แสดงไว้ที่นี่{% set left_list = left_list|merge({ (key): value }) %}

นี่คือโซลูชั่นที่สมบูรณ์

{% set left_list = {} %}
{% set right_list = {} %}
{% set limit = data|length // 2 %}
{% for key, value in data|cast_to_array %}
{% if key != 'password' %}
{% if loop.index <= limit %}
{% set left_list = left_list|merge({ (key): value }) %}
{% else %}
{% set right_list = right_list|merge({ (key): value }) %}
{% endif %}
{% endif %}
{% endfor %}
{% for key, value in left_list %}
<p>
<label for="{{key}}">{{key}}</label>
<input type="text" name="{{key}}" id="{{key}}" value="{{value}}"
       class="text ui-widget-content ui-corner-all">
</p>
{% endfor %}

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