कस्टम ब्लॉकों पर कैश संदर्भ सेट करने का सही तरीका क्या है?


13

मैंने एक ऐसे मुद्दे पर भाग लिया है जहां एक ब्लॉक जो प्रति पृष्ठ अद्वितीय होना चाहिए, लॉग-आउट उपयोगकर्ताओं के लिए नहीं है। मुद्दा एक कस्टम ब्लॉक प्लगइन है जिसमें मेरे पास एक खोज खोज पृष्ठ है जिसमें कस्टम फ़िल्टर शामिल हैं (उजागर फ़िल्टर के लिए कस्टम प्रतिस्थापन की तरह। ब्लॉक / व्यवस्थापक / संरचना / ब्लॉक के माध्यम से रखा गया है)।

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']]
    ];

  }

लेकिन ऐसा लगता है कि यह गलत होना चाहिए क्योंकि जब लॉग-आउट किया जाता है, तो ब्लॉक पहले दृश्य पर कैश हो जाता है, और जब यूआरएल बदल जाता है, तो यह ब्लॉक का एक नया संस्करण नहीं दिखा रहा था।

मुझे लगा कि यह वह दृश्य पृष्ठ हो सकता है जो समस्या पैदा कर रहा था, लेकिन जब मैंने दृश्य पृष्ठ पर कैशिंग बंद किया, तब भी यह मुद्दा बना रहा।

मैं इस मुद्दे को कई तरीकों से ठीक करने में सक्षम था, उदाहरण के लिए, एक preprocess_block हुक का उपयोग करके:

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

लेकिन इसने मुझे परेशान किया मैं कैश संदर्भों को अपने ब्लॉक के बिल्ड ऐरे में नहीं डाल सका।

चूँकि मेरा ब्लॉक ब्लॉकबेस का विस्तार करता है, इसलिए मैंने 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"
]

मैं यह पता लगाने की कोशिश कर रहा हूं कि यह कैसे काम करता है, और यह बिल्ड फ़ंक्शन से क्यों काम नहीं कर रहा था।

Viewcore () फ़ंक्शन पर /core/modules/block/src/BlockViewBuilder.php को देखते हुए, ऐसा लगता है कि यह इकाई और प्लगइन से कैश टैग को खींचता है:

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

तो यह बताता है कि मेरे ब्लॉक प्लगइन में getCacheContexts () पद्धति को जोड़ने से मेरे ब्लॉक में संदर्भ क्यों जुड़ते हैं। इसके अलावा, एक ही कक्षा में प्रेंडरेंडर पद्धति को देखते हुए, ऐसा लगता है कि यह ब्लॉक बिल्ड फ़ंक्शन में कैश ऐरे का उपयोग नहीं करता है, जो मुझे भ्रमित करता है, क्योंकि ऐसा लगता है कि Drupal 8 में कैशिंग जोड़ने का तरीका #cache जोड़ना है तत्वों को प्रस्तुत करने के लिए तत्व।

तो मेरा सवाल है,

1) क्या कैश संदर्भों को सीधे ब्लॉक प्लगइन में सरणी पर जोड़ा गया है?

2) यदि ऐसा है, तो क्या इसके आसपास कोई रास्ता है, क्या हमें इसे बिल्ड ऐरे के चाइल्ड एलिमेंट में जोड़ने की जरूरत है?

3) अगर संदर्भ को सीधे तौर पर नजरअंदाज किया जाता है, तो एक getCacheContexts () को कस्टम मॉड्यूल में ब्लॉक प्लगइन्स के लिए जाने का तरीका जोड़ रहा है?


1
1) नहीं, आपकी ब्लॉक सामग्री वास्तव में नीचे स्तर की है और बाद में विलय कर दी जानी चाहिए। 2) आवश्यक नहीं है क्योंकि 1, 3) getCacheContexts () को लागू करना आसान / क्लीनर हो सकता है लेकिन इसकी आवश्यकता नहीं होनी चाहिए। आप गुमनाम उपयोगकर्ताओं का स्पष्ट रूप से उल्लेख करते हैं, क्या आप सुनिश्चित हैं कि यह सामान्य प्रमाणित उपयोगकर्ताओं को भी प्रभावित नहीं करता है? यदि आप डायनेमिक_पेज_ कैश को अक्षम करते हैं तो समस्या दूर हो जाती है? कुछ अजीब होना चाहिए अगर यह केवल एनोन उपयोगकर्ताओं को प्रभावित करता है, क्योंकि आंतरिक पेज कैश हमेशा url / क्वेरी के द्वारा भिन्न होता है।
बर्दिर

1
डायनेमिक पेज कैश को अक्षम करने से समस्या ठीक नहीं होती है।
ओकेनेट करें

1
हम्म, यह इस तथ्य के साथ एक समस्या हो सकती है कि आपके शीर्ष स्तर के तत्व में # कैश के अलावा कुछ भी नहीं है। क्या आपने अपने फॉर्म में केवल # कैश सेट करने की कोशिश की है? यह वह रूप है जो उन लोगों द्वारा अलग-अलग करने की आवश्यकता है, और चूंकि कैश टैग बबल अप करते हैं, जो कि बस काम करना चाहिए। और यदि आप कभी भी अपने फॉर्म का उपयोग किसी अलग ब्लॉक या अन्य जगह पर करते हैं, तो यह भी वहां काम करना चाहिए।
बर्दिर

1
मैंने जल्दी से सिंडिकेटब्लॉक को हैक कर लिया और इस बिल्ड () विधि: gist.github.com/Berdir/33a31b1e98caf080dae78adb731dba4c का उपयोग किया । यह कहते हुए कि मेरी साइट ठीक काम करती है, कैश संदर्भ कैश_रेंडर तालिका में दिखाई देते हैं और सही अनुरोध URI प्रदर्शित होता है। क्या आप भी यही कोशिश कर सकते हैं? मुझे लगता है कि आपकी साइट पर बहुत कुछ अजीब चल रहा है
बर्दिर

2
क्या आप मानक ब्लॉक टेम्पलेट या कस्टम एक का उपयोग करते हैं? देखें drupal.stackexchange.com/questions/217884/...
4k4

जवाबों:


9

ज्यादातर मामलों में, आप बस कैश संदर्भ को आपके बिल्ड () विधि में वापस रेंडर सरणी पर सेट करते हैं।

मैंने आखिरकार पाया कि मेरा मुद्दा क्या था, @Berdir और @ 4k4 की मदद से। यदि आप एक कस्टम टेम्पलेट का उपयोग कर रहे हैं, जैसे कि ब्लॉक - myblock.html.twig और आप वैरिएबल को व्यक्तिगत रूप से आउटपुट करते हैं, जैसे {{सामग्री}}, एक ही समय में {{content.foo}} जैसे सभी के बजाय, यह अनदेखा करता है। जब लॉग आउट किया जाता है तो आपका कैश संदर्भ सीधे आपके ब्लॉक बिल्ड ऐरे में पास हो जाता है। देखें कि कस्टम ब्लॉक पर कैश संदर्भ सेट करने का सही तरीका क्या है?

तो, मूल प्रश्न का उत्तर देने के लिए:

1) कैश संदर्भों को एक कस्टम ब्लॉक प्लगइन में सीधे पारित कर दिया जाता है, कभी-कभी इसे अनदेखा कर दिया जाता है। आप SyndicateBlock को बदलकर , और फिर अपने थीम ब्लॉक में एक कस्टम टेम्पलेट बना सकते हैं - सिंडिकेट.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

तो आप एक नया थीम टेम्पलेट बनाने का सुझाव देंगे? स्पष्ट बुदबुदाहट को संरक्षित करने के लिए?
oknate

हां, ब्लॉक टेम्पलेट का उपयोग केवल बाहर की चीजों को जोड़ने के लिए करें। निर्माण में ब्लॉक के अंदर का निर्माण ()। इसके लिए कस्टम टेम्प्लेट का उपयोग करें या रेंडर करने वाले तत्वों का उपयोग करें, जैसे टेबल या लिंक की तरह एक कोर टेम्प्लेट।
4k4

ठीक है, मैं जवाब अपडेट कर दूंगा।
oknate

उह, मुझे महसूस नहीं हुआ कि ट्विग की ड्रिलिंग कैचएबल मेटाडेटा को अनदेखा कर देगी। इसका मतलब यह हो सकता है कि हमें ड्रिल करने के लिए अंत में अपनी स्वयं की कस्टम विधि का उपयोग करने की आवश्यकता है (जो कि टहनी विस्तार को बेकार कर देता है) ताकि हम निचले स्तरों में जाने के दौरान मेटाडेटा को संरक्षित करें। अच्छा खोजो!
लायंसएड

4

किसी और के लिए जो इसे पाता है ...

रेंडरिंग content(या content|without()) कार्य करने का कारण यह है कि रेंडर सरणी में एक तत्व content['#cache']है जिसमें सामग्री के लिए सभी उपलब्ध मेटाडेटा शामिल हैं।

यदि आप इसे टहनी में प्रस्तुत करने की अनुमति नहीं देते हैं, तो contentया तो {{'#cache': content['#cache']|render }}, पृष्ठ को यह पता नहीं है कि इसमें परिवर्तनशील मेटाटाटा है (जैसे। यह कभी बुलबुले नहीं बनता है)।

लगता है जैसे आप कस्टम टहनी नहीं कर रहे हैं। यदि आप वार्निश जैसी किसी चीज़ का उपयोग कर रहे हैं, तो यह अनाम उपयोगकर्ताओं के लिए भी एक अपराधी हो सकता है।


3

मैं इस मुद्दे में भी भाग गया और जो वर्कअराउंड मैं लेकर आया, वह मुख्य सामग्री चर के फ़िल्टर किए गए संस्करण के आधार पर एक नया ब्लॉक_ कॉन्टेंट वैरिएबल बनाने के लिए था, जिसे मैं किसी भी कस्टम फील्ड को छोड़कर मैन्युअल रूप से रेंडर करना चाहता हूं:

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

इसके बाद सीधे "content.body" चर का प्रतिपादन करने के बजाय, मैं कॉल करता हूं:

{{ 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.