2

I need to have a custom block on the page (will be sitewide) that has two states - one for when a cookie is present and has a certain value, and the other for when that cookie is not there or the value is outdated. Think of it like login states, but no authentication through Drupal.

What is the proper way to go about this with the block build() method? Do I implement a lazy loader that has the logic in it that builds the render array? Do I also add a cache context based on this cookie and its value so it is unique to those users?

9
  • 1
    Drupal 8 lazy-builds blocks which are cacheable by user and delivers them via AJAX (BigPipe) out of the box. Why not implement an alternative authentication provider and use it as it is? Or use at least a session cookie which Drupal can handle much better than a standard cookie. For the latter it is probably a better idea to initiate lazy-loading via AJAX in client-side js code.
    – 4k4
    Sep 20 '19 at 6:37
  • 1
    Well it’s not really auth, that was just an example of a block state (Login / Logout). I’m reading an externally set cookie and rendering state based on that.
    – Kevin
    Sep 20 '19 at 12:07
  • 1
    Drupal is not very good at handling cookies other than session cookies. Did you consider a client-side js solution?
    – 4k4
    Sep 20 '19 at 12:27
  • 1
    I’ll have to check with some front end folks on pure JS solution.
    – Kevin
    Sep 20 '19 at 12:49
  • 1
    So even if we use the setCookie/getCookie method from Symfony, it will be problematic? I don't see many references to cookies in Drupal, and user_save_cookie/user_delete_cookie looks deprecated and unused. I don't need to really set or save one, just read one.
    – Kevin
    Sep 20 '19 at 14:27
2

You can get the cookie from the request, see Can't find cookie for validation in EventSubscriber. Set the context and trigger the kill switch like in the code example and it should work. But this is not good for performance. So I would deliver an empty block container, attach a js library to the block, get the cookie value client side and then initiate an ajax request to get the block content.

See the code of the module Ajax Block as example how to lazy load a block client side: https://git.drupalcode.org/project/block_ajax

3
  • 1
    Unfortunately that module does not seem to work for anonymous users, and fails under functional tests (ajaxId is undefined). I also cannot seem to return a render array, I am limited to #markup in my block only. Do you have a possible simpler example on hand that does not need that module?
    – Kevin
    Sep 21 '19 at 20:14
  • 1
    Scratch that - my block is working and rendering, and seemingly loading with the Block Ajax module. But something about that module is preventing me from effectively writing a test and checking 1 of 3 possible responses based on the cookie value. I can use different browsers and see it manually, but would like to provide a test.
    – Kevin
    Sep 21 '19 at 23:06
  • 1
    By example I didn't meant the module itself, only the scaffolding consisting of a block plugin, empty or containing static default content like "Logged out", a js library containing the logic to check for the cookie and an ajax controller returning the dynamic block content.
    – 4k4
    Sep 22 '19 at 7:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.