0

I've got a content type called SERVICE (I write it all capitalized to prevent mixture with drupal service) which admin can introduce different SERVICE using this type, it is expected that these SERVICES be shown in main menu automatically, so I provided a menu plugin deriver which fetches the list of all published SERVICES

The problem is that event of inserting, editing or deleting of a service, does not change the menu as it is cached, so I write a service (not the content type this time) called ServiceEventListner which implements EventSubscriberInterface (provided by Hook Event Dispatcher Module) there I used to rebuild cache on insert, delete and update of SERVICE using the code:

\Drupal::cache('menu')->invalidateAll();     
\Drupal::service('plugin.manager.menu.link')->rebuild();
\Drupal::cache('block')->invalidateAll();

I was able to rebuild cache and menu but for a best practice I decided to inject the cache service rather than calling it directly so I passed CacheBackendInterface as a parameter to my service, but I can't handle to invalidate menu and block bin

The problem is when I inject CacheBackendInterface into my service it has no method to select certain bin and only has invalidate($cid) ,invalidateAll() and invalidateMultiple($cids) methods.

how can I select a certain bin in this case and invalidate all it's corresponding items?

mymoule.services.yml is as follows:

mymodule.node_service_update_listener:
class: Drupal\radis_request_customizer\Service\ServiceEventListner
arguments:
  - '@keyvalue'
  - '@entity_type.manager'
  - '@language_manager'
  - '@messenger'
  - '@cache.entity' <- the injected cache service
tags:
  - { name: event_subscriber }

and this is my construct method:

public function __construct(KeyValueFactory $keyValue, EntityTypeManager $entityService, LanguageManager $language, Messenger $messenger, CacheBackendInterface $cache) {
  $this->cacheStore = $keyValue;
  $this->entityService = $entityService;
  $this->myLanguageManager = $language;
  $this->myMessenger = $messenger;
  $this->myCache = $cache;
}

and finally this is my update method in service:

function updateMenu(EntityInsertEvent $event) {
  if ($event->getEntity()->getEntityTypeId() == 'node' and $event->getEntity()
    ->bundle() == 'service') {
    //TODO: CLEAR CACHE AND REBUILD MENU
    $this->myCache->invalidate('block'); //myCache is the injected CacheBackedInterface
  }
}

should I inject cache differently?

5
  • Can you provide a code example? I think you need CacheFactory::get() in the process of instantiating a cache bin. But I'm not sure what the end goal of your question is, because Drupal standard is that each cache bin has such a service instance already defined. – 4k4 May 10 at 8:02
  • @4k4 thanks for reply, I updated the question – Alireza Tabatabaeian May 10 at 8:44
  • What did you inject in mycache, isn't that already an instantiated cache bin? Then you need to inject it twice, for menu and block. The latter is not in core by the way, it has to be contrib or custom. – 4k4 May 10 at 8:57
  • @4k4 sorry, now I added services.yml and __construct method too – Alireza Tabatabaeian May 10 at 9:07
  • Injecting @cache.entity results in $this->myCache->invalidateAll() being the same as \Drupal::cache('entity')->invalidateAll() – 4k4 May 10 at 9:19

Your Answer

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

Browse other questions tagged or ask your own question.