Score:0

How can I bust the cache for the toolbar?

np flag

I am creating a drupal module and here in the module file i created a check on hook_toolbar() function that if there are credentials in the database it will show 4 links in dropdown otherwise it will show only 2 links. Initially with no credentials it shows 2 links but whenever i get credentials and update them in the database i have to clear cache in order to update the tray in the hook_toolbar() in order to show 4 links.

function try_toolbar() {
    $items = [];
    \Drupal::service('page_cache_kill_switch')->trigger();
    $items['TRY'] = [
        '#cache' => [
            'contexts' => ['user.permissions'],
        ],
    ];

    if (!\Drupal::currentUser()->hasPermission('Access the Commande overview page')) {
        return $items;
    }

    $credentials = db_select('config', 'n')
        ->fields('n')
        ->condition('collection', 'TRY','=')
        ->execute()
        ->fetchAssoc();
    $opValue = $credentials['data'];
    
    if($credentials) {
        $items['TRY'] += [
            '#type' => 'toolbar_item',
            '#weight' => 1,
            'tab' => [
                '#type' => 'link',
                '#title' => 'TRY',
                '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try"),
                '#attributes' => [
                    'title' => 'try menu',
                    'class' => ['toolbar-icon', 'toolbar-icon-try'],
                ],
            ],
            'tray' => [
    
                'configuration' => [
                    '#type' => 'link',
                    '#title' => 'Dashboard',
                    '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try_dashboard"),
    
                ],[
                    '#type' => 'link',
                    '#title' => 'Notifications',
                    '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try_notifications"),
                ],[
                    '#type' => 'link',
                    '#title' => 'Settings',
                    '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try_settings"),
                ],[
                    '#type' => 'link',
                    '#title' => 'Help',
                    '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try_help"),
                ],
    
            ],
            '#attached' => array(
                'library' => array(
                    'try/admin',
                ),
            ),
    
        ];
        return $items;

    } else {
        $items['TRY'] += [
            '#type' => 'toolbar_item',
            '#weight' => 1,
            'tab' => [
                '#type' => 'link',
                '#title' => 'TRY',
                '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try"),
                '#attributes' => [
                    'title' => 'try menu',
                    'class' => ['toolbar-icon', 'toolbar-icon-try'],
                ],
            ],

            'tray' => [
    
                'configuration' => [
                    '#type' => 'link',
                    '#title' => 'On Board',
                    '#url' => \Drupal\Core\Url::fromUri("internal:/admin/onBoard"),
    
                ],[
                    '#type' => 'link',
                    '#title' => 'Verify Credentials',
                    '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try_settings/verifyCredentials"), 
                ]
    
            ],
            '#attached' => array(
                'library' => array(
                    'try/admin',
                ),
            ),
    
        ];
        return $items;
    }
}

Here i used the following code to disable the cache

\Drupal::service('page_cache_kill_switch')->trigger();

But it is not working thus forcing me to manually clear the cache.

Please tell me a way to bust the cache depending on that database result.

id flag
You set a max-age if 0, but this is subject to limitations. https://www.drupal.org/docs/drupal-apis/cache-api/cache-max-age You would do much better by creating a cache context for the credentials existence, then varying the render array cache by that context instead of resorting to max-age.
Manav Chauhan avatar
np flag
can you tell me where do i have to add max-age = 0. @cilefen
Score:3
de flag

Setting max-age to zero, as well as using the killswitch you have in your code \Drupal::service('page_cache_kill_switch')->trigger();, are both sledgehammer solutions to a problem that Drupal is built to handle with finesse. Rather than rebuilding the menu on every page load, a cache tag is added to the render array. Then when the DB credentials for that user are cleared, that cache tag is invalidated. The next time it is requested by a user who matches the invalidated cache tage, it will be rebuilt and re-cached.

You can add a cache tag to your existing cache declaration on the render array as follows:

'#cache' => [
  'contexts' => ['user.permissions'],
  // Might be 'tag' not 'tags'. I can't remember which.
  // Tag is in the format [IDENTIFIER]:[USERID].
  'tags' => 'example_credentials:' . \Drupal::currentUser()->id(),
],

Then, when the toolbar should be rebuilt, which in your case is when the user submits their new credentials to be saved, you invalidate that cache tag:

Drupal\Core\Cache\Cache::invalidateTags()

If your menu isn't user specific, but rather role specific, permission specific, or some other metric, change the references to current user ID to some other identifier that for that role, or that permission, or whatever suits your needs. If no specificity is required at all - IE the menu items should be built for all users (to whom the cache context applies), you can remove the specific identifier altogether, and just use [IDENTIFIER], which in the above example is example_credentials.

Manav Chauhan avatar
np flag
I am not getting that where do i have to make changes in my code. Can you please guide through my code.
Jaypan avatar
de flag
I only gave you the one change. You just add the `tags` key to your #cache render array. For the other part, it depends on how the credentials are saved to the DB - it's probably a form, so you probably want to invalidate the tags in the submit handler for that form.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.