スキル一覧に戻る
sparkfabrik

drupal-cache-contexts

by sparkfabrik

This is an experimental repository to collect github copilot reusable instructions

1🍴 0📅 2026年1月19日
GitHubで見るManusで実行

SKILL.md


name: drupal-cache-contexts description: Drupal cache contexts implementation guide. Use when asked about request-based cache variations, user.roles vs user context, URL contexts, language contexts, custom cache contexts, or cache context hierarchy. Helps prevent cache explosion from overly broad contexts.

Drupal Cache Contexts

Cache contexts define request-dependent cache variations. Analogous to HTTP Vary header.

When to Use

  • Content varies by user role or permissions
  • Content changes based on URL parameters
  • Multi-language sites with localized content
  • Theme-dependent rendering
  • Preventing cache explosion from overly broad contexts

Available Contexts

ContextVariationsUse Case
userPer-user (AVOID)Truly personalized content only
user.rolesPer-role combinationRole-based visibility
user.permissionsPer-permission setPermission-based content
url.pathPer-pathPath-dependent content
url.query_args:keyPer-parameterSort, filter, pagination
languages:language_interfacePer-languageTranslated content
themePer-themeTheme-specific rendering
sessionPer-sessionSession data (triggers placeholder)

Context Hierarchy

user (AVOID - per-user cache explosion)
├── user.is_super_user (2 variations only)
├── user.roles (per role combination)
│   └── user.roles:editor (has specific role?)
└── user.permissions (per permission set)

Rule: Always use the most specific context possible.

Examples

Example 1: Role-Based Content

Input: "I show different content to editors vs anonymous users"

Output:

$build = [
  '#markup' => $this->getRoleBasedContent(),
  '#cache' => [
    'contexts' => ['user.roles'],
  ],
];

Example 2: Per-User Content (Use Sparingly)

Input: "I need to show the user's own profile info"

Output:

// WARNING: Creates cache entry per user - use lazy_builder instead
$build = [
  '#markup' => $user->getDisplayName(),
  '#cache' => [
    'contexts' => ['user'], // High cardinality!
  ],
];

// BETTER: Use lazy builder for per-user content
$build = [
  '#lazy_builder' => ['my_module.lazy:userName', []],
  '#create_placeholder' => TRUE,
];

Example 3: URL Query Parameters

Input: "My listing supports ?sort=date and ?sort=title parameters"

Output:

$sort = \Drupal::request()->query->get('sort', 'date');

$build = [
  '#theme' => 'item_list',
  '#items' => $this->getSortedItems($sort),
  '#cache' => [
    'contexts' => ['url.query_args:sort'],
  ],
];

Example 4: Language-Dependent Content

Input: "I render translated labels in my block"

Output:

$build = [
  '#markup' => $this->t('Welcome'),
  '#cache' => [
    'contexts' => ['languages:language_interface'],
  ],
];

Example 5: Combined Contexts

Input: "Content varies by role AND language"

Output:

$build = [
  '#markup' => $this->getLocalizedRoleContent(),
  '#cache' => [
    'contexts' => [
      'user.roles',
      'languages:language_interface',
    ],
  ],
];

Example 6: Custom Cache Context

Input: "I need to vary cache by a custom HTTP header"

Output:

# my_module.services.yml
services:
  cache_context.custom_header:
    class: Drupal\my_module\Cache\CustomHeaderContext
    arguments: ['@request_stack']
    tags:
      - { name: cache.context }
namespace Drupal\my_module\Cache;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\Context\CacheContextInterface;

class CustomHeaderContext implements CacheContextInterface {

  public static function getLabel() {
    return t('Custom header');
  }

  public function getContext() {
    $request = $this->requestStack->getCurrentRequest();
    return $request->headers->get('X-Custom-Header', 'default');
  }

  public function getCacheableMetadata() {
    return new CacheableMetadata();
  }
}
// Usage
$build['#cache']['contexts'][] = 'custom_header';

Example 7: Block with Cache Contexts

Input: "My block shows different actions based on permissions"

Output:

class ActionBlock extends BlockBase {

  public function build() {
    $actions = [];
    if (\Drupal::currentUser()->hasPermission('edit content')) {
      $actions[] = 'Edit';
    }
    return ['#markup' => implode(', ', $actions)];
  }

  public function getCacheContexts() {
    return Cache::mergeContexts(
      parent::getCacheContexts(),
      ['user.permissions']
    );
  }
}

Common Mistakes

MistakeImpactSolution
Using user for role checksCache explosion (1 entry per user)Use user.roles
Using session directlyTriggers auto-placeholderUse lazy builder
Missing contextSame cached content for all variationsAdd appropriate context
Too broad contextUnnecessary cache variationsUse most specific context

Auto-Placeholdering

These contexts trigger automatic placeholdering in Dynamic Page Cache:

# services.yml - default conditions
renderer.config:
  auto_placeholder_conditions:
    contexts:
      - 'session'
      - 'user'

Content with these contexts is replaced with a placeholder and rendered separately.

Debugging

# Enable debug headers
$settings['http.response.debug_cacheability_headers'] = TRUE;

# Check applied contexts
curl -sI https://site.com/ | grep X-Drupal-Cache-Contexts
# Output: X-Drupal-Cache-Contexts: languages:language_interface theme url.path user.permissions

スコア

総合スコア

55/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

0/5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です