ワンクリックで
drupal-hooks
Drupal 11 OOP and procedural hooks — hook_form_alter, hook_node_presave, hook_theme,
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Drupal 11 OOP and procedural hooks — hook_form_alter, hook_node_presave, hook_theme,
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
HTMX in Drupal 11.3+ core — the Htmx PHP fluent builder, dynamic forms with swapOob, partial routes with _htmx_route, response headers, and Drupal.behaviors integration. Use when building interactive UI without full-page reloads using Drupal's native HTMX support.
DDEV local development expertise. Use when working with DDEV projects, containers, configuration, or troubleshooting DDEV environments.
Custom Docker Compose local development patterns. Use when working with Docker-based local environments, container configuration, or troubleshooting Docker setups.
Drupal access control — permissions.yml, access callbacks, AccessResult, custom access checkers, and entity access.
Drupal Cache API — cache tags, contexts, max-age, cache bins, invalidation, and adding cache metadata to render arrays.
Drupal Composer management — requiring modules, updates, patches via composer-patches, and version constraints.
| name | drupal-hooks |
| description | Drupal 11 OOP and procedural hooks — hook_form_alter, hook_node_presave, hook_theme, |
| Location | src/Hook/MyModuleHooks.php |
| Namespace | Drupal\my_module\Hook |
| Auto-registered | Drupal 11.1+ (no services.yml needed) |
| DI support | Constructor injection |
| Testable | Yes — instantiate directly, inject mocks |
<?php
namespace Drupal\my_module\Hook;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\node\NodeInterface;
final class MyModuleHooks {
use StringTranslationTrait; // Provides $this->t().
public function __construct(
private readonly AccountProxyInterface $currentUser,
) {}
/**
* Implements hook_form_node_article_form_alter().
*
* Prefer targeted form hooks over generic form_alter — they only fire for
* the specific form ID and avoid unnecessary processing.
*/
#[Hook('form_node_article_form_alter')]
public function formNodeArticleFormAlter(array &$form, FormStateInterface $form_state): void {
$form['title']['#title'] = $this->t('Article title');
}
/**
* Implements hook_form_alter().
*
* Use only when acting on multiple forms or the form ID is unknown at
* development time. Check $form_id explicitly.
*/
#[Hook('form_alter')]
public function formAlter(array &$form, FormStateInterface $form_state, string $form_id): void {
if ($form_id === 'node_page_form') {
$form['title']['#description'] = $this->t('Enter a descriptive page title.');
}
}
#[Hook('node_presave')]
public function nodePresave(NodeInterface $node): void {
if ($node->getType() === 'article') {
// Example: stamp the current user's ID on save.
$node->set('uid', $this->currentUser->id());
}
}
#[Hook('theme')]
public function theme(): array {
return [
'my_template' => [
'variables' => ['content' => NULL],
],
];
}
}
Note: If a hook is not executed, verify namespace and location. OOP hooks outside
src/Hook/require manual service registration.
| Scenario | Required? |
|---|---|
Class in src/Hook/, namespace Drupal\my_module\Hook | No — auto-registered (Drupal 11.1+) |
Class outside src/Hook/ (e.g. a custom service) | Yes — register manually |
When registration is needed — autowire resolves constructor dependencies by type hint:
namespace Drupal\my_module\Service;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Session\AccountProxyInterface;
final class MyCustomService {
public function __construct(
private readonly AccountProxyInterface $currentUser,
) {}
#[Hook('form_alter')]
public function formAlter(...): void {
// ...
}
}
services:
Drupal\my_module\Service\MyCustomService:
autowire: true
Auto-discovered via my_module_hook_name() naming. Still valid; prefer OOP hooks for new code.
| Use Hooks When | Use Event Subscribers When |
|---|---|
form_alter, entity hooks, theme hooks | reacting to dispatched Symfony events |
| extending Drupal core/contrib behavior | PSR-14 / decoupled systems |
| working with existing Drupal APIs | building loosely coupled logic |
OOP hooks in
src/Hook/are fully testable — instantiate the class directly and inject mocked dependencies.
src/Hook/ for new implementations.module unless explicitly requested