원클릭으로
drupal-plugins
Drupal plugin system — Block, Field, Condition, Filter plugins with PHP attributes and ContainerFactoryPluginInterface.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Drupal plugin system — Block, Field, Condition, Filter plugins with PHP attributes and ContainerFactoryPluginInterface.
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-plugins |
| description | Drupal plugin system — Block, Field, Condition, Filter plugins with PHP attributes and ContainerFactoryPluginInterface. |
// src/Plugin/Block/MyBlock.php
namespace Drupal\my_module\Plugin\Block;
use Drupal\Core\Block\Attribute\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
#[Block(
id: 'my_block',
admin_label: new TranslatableMarkup('My Block'),
category: new TranslatableMarkup('Custom'),
)]
final class MyBlock extends BlockBase implements ContainerFactoryPluginInterface {
use StringTranslationTrait;
public function __construct(
array $configuration,
string $plugin_id,
mixed $plugin_definition,
private readonly EntityTypeManagerInterface $entityTypeManager,
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity_type.manager'),
);
}
public function build(): array {
return [
'#markup' => $this->t('Hello from my block.'),
'#cache' => [
'tags' => ['node_list'],
'contexts' => ['user.permissions'],
],
];
}
}
Note: Plugins are discovered via attributes (or annotations in legacy code), not services.yml.
Use PHP attributes (Drupal 10.2+, required style for Drupal 11):
#[Block(id: 'my_block', admin_label: new TranslatableMarkup('My Block'))]
Legacy (discouraged):
// @Block(id = "my_block", admin_label = @Translation("My Block"))
public function defaultConfiguration(): array {
return ['limit' => 5];
}
public function blockForm(array $form, FormStateInterface $form_state): array {
$form['limit'] = [
'#type' => 'number',
'#title' => $this->t('Limit'),
'#default_value' => $this->configuration['limit'],
];
return $form;
}
public function blockSubmit(array $form, FormStateInterface $form_state): void {
$this->configuration['limit'] = $form_state->getValue('limit');
}
drush generate plugin:block
drush generate plugin:field:formatter
drush generate plugin:field:widget
drush generate plugin:field:type
drush generate plugin:condition
drush generate plugin:filter
| Discovery | Via PHP attributes (or legacy annotations) — not services.yml |
| Instantiation | By plugin managers, not the service container |
| DI | Requires ContainerFactoryPluginInterface |
| Manager | Each plugin type has its own manager (e.g., BlockManager) |
| Plugin ID | Must be unique — used internally by Drupal to identify the plugin |