วิธีที่ถูกต้องในการตั้งค่าบริบทแคชบนบล็อกที่กำหนดเองคืออะไร?


13

ฉันพบปัญหาที่บล็อกที่ไม่ซ้ำใครต่อหน้าไม่ใช่สำหรับผู้ใช้ที่ออกจากระบบ ปัญหาคือปลั๊กอินบล็อกที่กำหนดเองที่ฉันมีในหน้าค้นหามุมมองที่มีตัวกรองแบบกำหนดเอง (เรียงลำดับเหมือนการแทนที่แบบกำหนดเองสำหรับตัวกรองแบบเปิดเผยบล็อกที่วางผ่าน / admin / โครงสร้าง / บล็อก)

จากสิ่งที่ฉันได้เรียนรู้เกี่ยวกับ Drupal 8 ฉันได้เพิ่มบริบทแคชไปยังอาร์เรย์บิลด์ของฉัน:

  public function build() {

    $search_form = \Drupal::formBuilder()->getForm('Drupal\mymodule\Form\SearchForm');
    return [
      'search_form' => $search_form,
      '#cache' => ['contexts' => ['url.path', 'url.query_args']]
    ];

  }

แต่ดูเหมือนว่าสิ่งนี้จะต้องไม่ถูกต้องเพราะเมื่อออกจากระบบบล็อกจะถูกแคชในมุมมองแรกและเมื่อ URL เปลี่ยนไปมันจะไม่แสดงบล็อกเวอร์ชันใหม่

ฉันคิดว่าอาจเป็นหน้าการดูที่ทำให้เกิดปัญหา แต่แม้ว่าฉันจะปิดการแคชในหน้าการดูปัญหายังคงอยู่

ฉันสามารถแก้ไขปัญหาได้หลายวิธีตัวอย่างเช่นโดยใช้ตะขอ preprocess_block:

function mymodule_preprocess_block__mycustomsearchblock(&$variables) {
  $variables['#cache']['contexts'][] = 'url.path';
  $variables['#cache']['contexts'][] = 'url.query_args';
}

แต่มันรบกวนฉันฉันไม่สามารถใส่บริบทของแคชในอาร์เรย์ประกอบการบล็อกของฉันได้

เนื่องจากบล็อกของฉันขยาย BlockBase ฉันจึงตัดสินใจลองใช้เมธอด getCacheContexts () โดยเฉพาะอย่างยิ่งเมื่อฉันเห็นโมดูลบางอย่างในคอร์กำลังทำแบบนี้

  public function getCacheContexts() {
    return Cache::mergeContexts(parent::getCacheContexts(), ['url.path', 'url.query_args']);
  }

สิ่งนี้ได้รับการแก้ไขด้วยเช่นกัน แต่ที่น่าสนใจเมื่อฉันแสดงตัวแปรในฟังก์ชั่นบล็อกก่อนการประมวลผลสิ่งเหล่านี้จะไม่แสดงในตัวแปร $ ['# แคช'] ['บริบท'] แต่แสดงในองค์ประกอบ $ ตัวแปร ['องค์ประกอบ '] [' # แคช '] [' บริบท]

array:5 [▼
  0 => "languages:language_interface"
  1 => "theme"
  2 => "url.path"
  3 => "url.query_args"
  4 => "user.permissions"
]

ฉันพยายามหาวิธีการใช้งานและทำไมมันไม่ทำงานจากฟังก์ชั่นการสร้าง

ดูที่ /core/modules/block/src/BlockViewBuilder.php ที่ฟังก์ชั่น viewMultiple () ดูเหมือนว่าจะดึงแท็กแคชจากเอนทิตีและปลั๊กอิน:

'contexts' => Cache::mergeContexts(
  $entity->getCacheContexts(),
  $plugin->getCacheContexts()
),

ดังนั้นอธิบายว่าทำไมการเพิ่มเมธอด getCacheContexts () ลงในปลั๊กอินบล็อกของฉันเพิ่มบริบทลงในบล็อกของฉัน นอกจากนี้การดูเมธอด preRender ในคลาสเดียวกันดูเหมือนว่าไม่ได้ใช้อาร์เรย์แคชในฟังก์ชันการสร้างบล็อกซึ่งทำให้ฉันสับสนเพราะดูเหมือนว่าวิธีเพิ่มแคชใน Drupal 8 คือการเพิ่ม #cache องค์ประกอบที่จะแสดงองค์ประกอบ

ดังนั้นคำถามของฉันคือ

1) มีการเพิ่มบริบทแคชโดยตรงในอาร์เรย์ในปลั๊กอินบล็อกที่ถูกละเว้นหรือไม่?

2) ถ้าใช่มีวิธีแก้ไขไหมเราต้องเพิ่มมันเข้าไปในองค์ประกอบย่อยของ build อาร์เรย์หรือไม่?

3) หากบริบทถูกเพิ่มโดยตรงถูกเพิกเฉยการเพิ่ม getCacheContexts () วิธีที่จะใช้สำหรับบล็อกปลั๊กอินในโมดูลที่กำหนดเองได้หรือไม่


1
1) ไม่เนื้อหาบล็อกของคุณอยู่ในระดับที่ต่ำกว่าและควรจะรวมในภายหลัง 2) ไม่จำเป็นเนื่องจาก 1, 3) การใช้ getCacheContexts () สามารถทำได้ง่ายขึ้น / สะอาดขึ้น แต่ไม่จำเป็นต้องใช้ คุณพูดถึงผู้ใช้ที่ไม่ระบุชื่ออย่างชัดเจนคุณแน่ใจหรือไม่ว่ามันไม่ส่งผลกระทบต่อผู้ใช้ที่ผ่านการตรวจสอบสิทธิ์ปกติ ปัญหาหายไปหรือไม่หากคุณปิดการใช้งาน dynamic_page_cache สิ่งที่แปลกประหลาดจะต้องเกิดขึ้นหากมีผลกระทบต่อผู้ใช้รายเดียวเนื่องจากแคชของเพจภายในจะแตกต่างกันไปตาม url / แบบสอบถาม
Berdir

1
การปิดใช้งานแคชหน้าแบบไดนามิกไม่สามารถแก้ไขปัญหาได้
ตกลง

1
อืมอาจเป็นปัญหากับความจริงที่ว่าองค์ประกอบระดับบนสุดของคุณไม่มีสิ่งใดนอกจาก #cache คุณได้ลองตั้ง #cache ในฟอร์มของคุณแล้วหรือยัง? มันเป็นรูปแบบที่ต้องแตกต่างกันไปตามรูปแบบเหล่านั้นและเมื่อแท็กแคชเพิ่มขึ้นนั่นก็น่าจะใช้ได้ และถ้าคุณเคยใช้แบบฟอร์มของคุณในบล็อกที่แตกต่างกันหรือสถานที่อื่นมันก็ควรจะทำงานที่นั่น
Berdir

1
ฉันได้อย่างรวดเร็ว hacked SyndicateBlock และใช้โครงสร้างนี้ () วิธีการ: gist.github.com/Berdir/33a31b1e98caf080dae78adb731dba4c การวางให้เว็บไซต์ของฉันใช้งานได้ดีบริบทของแคชจะปรากฏในตาราง cache_render และแสดง URI คำขอที่ถูกต้อง คุณลองแบบเดียวกันได้ไหม ดูเหมือนว่าฉันจะมีบางสิ่งที่แปลกมากเกิดขึ้นในไซต์ของคุณ
Berdir

2
คุณใช้เทมเพลตบล็อกมาตรฐานหรือเทมเพลตที่กำหนดเองหรือไม่? ดูdrupal.stackexchange.com/questions/217884/…
4k4

คำตอบ:


9

ในกรณีส่วนใหญ่คุณเพิ่งตั้งค่าบริบทแคชโดยตรงบนเรนเดอร์เรนเดอร์ที่คุณส่งคืนในเมธอด build ()

ในที่สุดฉันก็พบว่าปัญหาของฉันคืออะไรด้วยความช่วยเหลือของ @Berdir และ @ 4k4 หากคุณกำลังใช้เท็มเพลตที่กำหนดเองเช่นบล็อก - myblock.html.twig และคุณส่งออกตัวแปรแต่ละรายการเช่น {{content.foo}} แทนทั้งหมดในเวลาเดียวกันเช่น {{content}} มันจะไม่สนใจ บริบทแคชของคุณส่งผ่านโดยตรงไปยังอาร์เรย์บล็อกการสร้างของคุณเมื่อออกจากระบบ ดูวิธีที่ถูกต้องในการตั้งค่าบริบทแคชบนบล็อกที่กำหนดเองคืออะไร

ดังนั้นเพื่อตอบคำถามเดิม:

1) บริบทแคชที่ส่งโดยตรงไปยังปลั๊กอินบล็อกที่กำหนดเองจะถูกละเว้นในบางครั้ง คุณสามารถทดสอบสิ่งนี้ได้โดยการแก้ไข SyndicateBlockจากนั้นสร้างเทมเพลตที่กำหนดเองในชุดรูปแบบบล็อกของคุณ - syndicate.html.php ซึ่งคุณส่งออกตัวแปรแต่ละรายการดังนี้:

{% block content %}
  {{ content.foo }}
{% endblock %}

เมื่อคุณเปลี่ยนอาร์กิวเมนต์ url คุณจะเห็นว่าบล็อกไม่เคารพบริบทแคช

ตอนนี้ถ้าคุณเปลี่ยนมันจะเอาท์พุทเนื้อหาทั้งหมดเป็นชิ้น ๆ แล้วก็ใช้งานได้:

{% block content %}
  {{ content }}
{% endblock %}

ตอนนี้จะเคารพบริบทแคชและบล็อกนั้นไม่ซ้ำกันต่อหน้า

2) สำหรับตอนนี้คุณสามารถส่งสิ่งที่อยู่ในบล็อกของคุณในเทมเพลตของตัวเองได้

 public function build() {

    $search_form = \Drupal::formBuilder()->getForm('Drupal\mymodule\Form\SearchForm');
    return [
      '#theme' => 'mycustomtemplate',
      '#search_form' => $search_form,
      '#cache' => ['contexts' => ['url.path', 'url.query_args']]
    ];

  }

สิ่งนี้จะหลีกเลี่ยงข้อยกเว้นการแคชที่ลึกลับของโมดูลบล็อกและตอนนี้ฟอร์มของคุณจะไม่ซ้ำกันต่อหน้าเมื่อออกจากระบบ

3) คุณควรสร้างเทมเพลตธีมของคุณเองเพื่อแก้ไขปัญหานี้หรือเพียงเพิ่มวิธีการสำหรับ getCacheContexts () ในปลั๊กอินบล็อกที่กำหนดเองของคุณ? เป็นการดีกว่าที่จะสร้างเท็มเพลตธีมใหม่แทนที่จะเพิ่มเมธอด getCacheContexts () ที่จะแทนที่ลำดับของบริบทแคชที่เป็นธรรมชาติและอาจทำให้เมตาดาต้าลึกลงไปในอาร์เรย์การสร้างของคุณ


นี่เป็นข้อสรุปที่ดีมากของปัญหา แต่ฉันคิดว่าข้อสรุปใน 3) เป็นปัญหาเพราะคุณไม่เพียง แต่ทำลายข้อมูลเมตาแคชของคุณเองเท่านั้นที่สามารถทำให้เกิดฟองขึ้น แต่สิ่งที่อาจอยู่ลึกเข้าไปในอาเรย์เรนเดอร์และคุณอาจไม่ทราบ
4k4

ดังนั้นคุณจะแนะนำให้สร้างเทมเพลตธีมใหม่หรือไม่ เพื่อรักษาฟองชัดเจน?
ตกลง

ใช่ใช้เทมเพลตบล็อกเท่านั้นเพื่อเพิ่มสิ่งภายนอก สร้างส่วนในของบล็อกใน build () ใช้เทมเพลตที่กำหนดเองสำหรับสิ่งนี้หรือใช้องค์ประกอบการแสดงผลเช่นตารางหรือเทมเพลตหลักเช่นลิงก์
4k4

ตกลงฉันจะอัพเดตคำตอบ
ตกลง

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

4

สำหรับคนอื่นที่พบสิ่งนี้ ...

เหตุผลที่การแสดงผลcontent(หรือcontent|without()) ทำงานคือมีองค์ประกอบในอาร์เรย์การแสดงผลcontent['#cache']ที่มีข้อมูลเมตาที่แคชทั้งหมดสำหรับเนื้อหา

หากคุณไม่อนุญาตให้มีการแสดงผลเป็นทวิอย่างใดอย่างหนึ่งcontentหรือ{{'#cache': content['#cache']|render }}หน้าเว็บไม่ทราบว่ามีข้อมูลเมตาที่แคชได้ (เช่นไม่เคยมีฟองอากาศ)

ดูเหมือนว่าคุณจะไม่ทำกิ่งไม้ที่กำหนดเองว่า หากคุณกำลังใช้สิ่งเช่นวานิชนั่นอาจเป็นสาเหตุของผู้ใช้ที่ไม่ระบุชื่อ


3

ฉันยังพบปัญหานี้และวิธีแก้ปัญหาที่ฉันพบคือสร้างตัวแปร block_content ใหม่โดยอิงจากเวอร์ชันเนื้อหาที่กรองของตัวแปรเนื้อหาหลักซึ่งไม่รวมฟิลด์ที่กำหนดเองใด ๆ ที่ฉันต้องการให้แสดงด้วยตนเอง:

{% set block_content = content|without('field_mycustomfield', 'field_mycustomfield2') %}

จากนั้นแทนที่จะแสดงตัวแปร "content.body" โดยตรงในภายหลังฉันโทรไปที่:

{{ block_content }}

หากคุณต้องการแสดงผลทุกช่องเป็นรายบุคคลคุณสามารถเพิ่มไปยังตัวกรอง "ไม่มี" เพื่อให้การแสดงผล block_content ไม่ได้ทำอะไรนอกจากการแก้ไขแคช


0

วิธีที่ง่ายกว่าในการบรรลุเป้าหมายนี้คือการประกาศและกำหนดgetCacheContexts()วิธีการ


  public function build() {

    $search_form = \Drupal::formBuilder()->getForm('Drupal\mymodule\Form\SearchForm');
    return [
      'search_form' => $search_form
    ];

  }

  /**
   * {@inheritdoc}
   */
  public function getCacheMaxAge() {
    // If you need to redefine the Max Age for that block
    return 0;
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheContexts() {
    return ['url.path', 'url.query_args'];
  }

ตรวจสอบเอกสารCacheableDependencyซึ่งควรมีทุกสิ่งที่คุณต้องการ;)


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