mcpField
D
drupal-backend

drupal-backend

github.com/omedia開発28104 回インストール53 週間前に更新
リポジトリ

drupal-backend について

drupal-backendは、Drupal 8から11+までのバックエンド開発向けスキルです。カスタムモジュール、Drupal API、フック、プラグイン、サービス、ルーティング、フォーム、データベース操作のパターンと例を提供します。

主な機能

  1. 01カスタムモジュールの雛形と構成
  2. 02フック、コントローラー、ルーティング
  3. 03フォームとエンティティ操作
  4. 04プラグイン、サービス、依存性注入
  5. 05データベースクエリとスキーマ定義
  6. 06開発とトラブルシューティングの指針

活用シーン

  1. 01Drupalカスタムモジュールの構築
  2. 02ルート、フォーム、プラグインの追加
  3. 03エンティティまたはデータベース操作の実装
  4. 04モジュールやAPIの問題調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/omedia/drupal-skill --skill drupal-backend

インストール後、Claude Code で/drupal-backendを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/module-template/
MODULENAME.info.yml
MODULENAME.module
MODULENAME.routing.yml
README.md
assets/module-template/src/Controller/
ExampleController.php
references/
hooks.md
module_structure.md

詳細

Drupal バックエンド開発

概要

エキスパートレベルの Drupal バックエンド開発機能を提供します。Drupal 8、9、10、11+ 向けのカスタムモジュール開発、PHP プログラミング、API の使用、フック、プラグイン、サービス、データベース操作に関する包括的なガイダンスを提供します。

このスキルを使用する場面

以下の作業を行う場合にこのスキルを呼び出してください:

  • カスタムモジュール開発: 新しい Drupal モジュールの作成
  • フック: システムの動作を変更する Drupal フックの実装
  • コントローラーとルーティング: カスタムページとルートの構築
  • フォーム: 設定フォームやカスタムフォームの作成
  • エンティティ: コンテンツエンティティまたは設定エンティティの操作
  • プラグイン: ブロック、フィールドタイプ、フォーマッター、その他のプラグインの構築
  • サービス: 再利用可能なビジネスロジックサービスの作成
  • データベース操作: カスタムクエリとスキーマ定義
  • API: Entity API、Form API、Database API、Plugin API

主な機能

1. カスタムモジュール開発

標準に準拠した完全な Drupal モジュールを作成します:

クイックスタートワークフロー:

  1. assets/module-template/ のモジュールテンプレートを使用します
  2. MODULENAME をマシン名(小文字、アンダースコア)に置き換えます
  3. MODULELABEL を人間が読める名前に置き換えます
  4. Drupal API を使用して機能を実装します
  5. モジュールを有効化してテストします:ddev drush en mymodule -y

モジュール構造:

  • .info.yml - モジュールのメタデータと依存関係
  • .module - フックの実装
  • .routing.yml - ルート定義
  • .services.yml - サービス定義
  • .permissions.yml - カスタムパーミッション
  • src/ - PHP クラス(PSR-4 オートローディング)
  • config/ - 設定ファイル

参考ドキュメント:

  • references/module_structure.md - 完全なモジュールパターン
  • references/hooks.md - フックの実装
2. フックシステム

Drupal の動作を変更するフックを実装します:

一般的なフック:

  • hook_entity_presave() - 保存前にエンティティを変更します
  • hook_entity_insert/update/delete() - エンティティの変更に反応します
  • hook_form_alter() - 任意のフォームを変更します
  • hook_node_access() - ノードへのアクセスを制御します
  • hook_cron() - 定期的なタスクを実行します
  • hook_install/uninstall() - モジュールのインストール時のタスク

フックのパターン:

function MODULENAME_hook_name($param1, &$param2) {
  // Implementation
}

ベストプラクティス:

  • フックは .module ファイルにのみ実装します
  • 適切な型ヒントを使用します
  • PHPDoc ブロックでドキュメント化します
  • 処理前にエンティティタイプを確認します
  • パフォーマンスに注意します
3. コントローラーとルーティング

カスタムページとエンドポイントを作成します:

ルート定義(.routing.yml):

mymodule.example:
  path: '/example/{param}'
  defaults:
    _controller: '\Drupal\mymodule\Controller\ExampleController::content'
    _title: 'Example Page'
  requirements:
    _permission: 'access content'
    param: \d+

コントローラーのパターン:

namespace Drupal\mymodule\Controller;

use Drupal\Core\Controller\ControllerBase;

class ExampleController extends ControllerBase {
  public function content() {
    return ['#markup' => $this->t('Hello!')];
  }
}

依存性注入を使用する場合:

public function __construct(EntityTypeManagerInterface $entity_type_manager) {
  $this->entityTypeManager = $entity_type_manager;
}

public static function create(ContainerInterface $container) {
  return new static($container->get('entity_type.manager'));
}
4. Form API

設定フォームとカスタムフォームを構築します:

設定フォーム:

class SettingsForm extends ConfigFormBase {
  protected function getEditableConfigNames() {
    return ['mymodule.settings'];
  }

  public function buildForm(array $form, FormStateInterface $form_state) {
    $config = $this->config('mymodule.settings');
    
    $form['api_key'] = [
      '#type' => 'textfield',
      '#title' => $this->t('API Key'),
      '#default_value' => $config->get('api_key'),
    ];
    
    return parent::buildForm($form, $form_state);
  }

  public function submitForm(array &$form, FormStateInterface $form_state) {
    $this->config('mymodule.settings')
      ->set('api_key', $form_state->getValue('api_key'))
      ->save();
    parent::submitForm($form, $form_state);
  }
}

フォームのバリデーション:

public function validateForm(array &$form, FormStateInterface $form_state) {
  if (strlen($form_state->getValue('field')) < 5) {
    $form_state->setErrorByName('field', $this->t('Too short.'));
  }
}
5. Entity API

コンテンツエンティティと設定エンティティを操作します:

エンティティの読み込み:

// Load single entity
$node = \Drupal::entityTypeManager()->getStorage('node')->load($nid);

// Load multiple entities
$nodes = \Drupal::entityTypeManager()->getStorage('node')->loadMultiple([1, 2, 3]);

// Load by properties
$nodes = \Drupal::entityTypeManager()->getStorage('node')->loadByProperties([
  'type' => 'article',
  'status' => 1,
]);

エンティティの作成/保存:

$node = \Drupal::entityTypeManager()->getStorage('node')->create([
  'type' => 'article',
  'title' => 'My Article',
  'body' => ['value' => 'Content', 'format' => 'basic_html'],
]);
$node->save();

エンティティクエリ:

$query = \Drupal::entityQuery('node')
  ->condition('type', 'article')
  ->condition('status', 1)
  ->accessCheck(TRUE)
  ->sort('created', 'DESC')
  ->range(0, 10);
$nids = $query->execute();
6. プラグインシステム

カスタムプラグイン(ブロック、フィールドなど)を作成します:

ブロックプラグイン:

/**
 * @Block(
 *   id = "mymodule_custom_block",
 *   admin_label = @Translation("Custom Block"),
 * )
 */
class CustomBlock extends BlockBase {
  public function build() {
    return ['#markup' => 'Block content'];
  }
  
  public function blockForm($form, FormStateInterface $form_state) {
    $form['setting'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Setting'),
      '#default_value' => $this->configuration['setting'] ?? '',
    ];
    return $form;
  }
  
  public function blockSubmit($form, FormStateInterface $form_state) {
    $this->configuration['setting'] = $form_state->getValue('setting');
  }
}
7. サービスと依存性注入

再利用可能なサービスを作成します:

サービス定義(.services.yml):

services:
  mymodule.custom_service:
    class: Drupal\mymodule\Service\CustomService
    arguments: ['@entity_type.manager', '@current_user']

サービスクラス:

namespace Drupal\mymodule\Service;

class CustomService {
  protected $entityTypeManager;
  protected $currentUser;

  public function __construct(EntityTypeManagerInterface $entity_type_manager, AccountProxyInterface $current_user) {
    $this->entityTypeManager = $entity_type_manager;
    $this->currentUser = $current_user;
  }

  public function doSomething() {
    // Business logic
  }
}
8. データベース操作

カスタムクエリを実行します:

Database API の使用:

$database = \Drupal::database();

// Select query
$query = $database->select('node_field_data', 'n')
  ->fields('n', ['nid', 'title'])
  ->condition('type', 'article')
  ->condition('status', 1)
  ->range(0, 10);
$results = $query->execute()->fetchAll();

// Insert
$database->insert('mymodule_table')
  ->fields(['name' => 'Example', 'value' => 123])
  ->execute();

// Update
$database->update('mymodule_table')
  ->fields(['value' => 456])
  ->condition('name', 'Example')
  ->execute();

スキーマ定義(.install ファイル):

function mymodule_schema() {
  $schema['mymodule_table'] = [
    'fields' => [
      'id' => ['type' => 'serial', 'not null' => TRUE],
      'name' => ['type' => 'varchar', 'length' => 255, 'not null' => TRUE],
      'value' => ['type' => 'int', 'not null' => TRUE, 'default' => 0],
    ],
    'primary key' => ['id'],
    'indexes' => ['name' => ['name']],
  ];
  return $schema;
}

開発ワークフロー

カスタムモジュールの作成
  1. モジュールをスキャフォールドします:

    cp -r assets/module-template/ /path/to/drupal/modules/custom/mymodule/
    cd /path/to/drupal/modules/custom/mymodule/
    mv MODULENAME.info.yml mymodule.info.yml
    mv MODULENAME.module mymodule.module
    mv MODULENAME.routing.yml mymodule.routing.yml
    
  2. モジュールファイルを更新します:

    • MODULENAME をマシン名に置き換えます
    • MODULELABEL を読みやすい名前に置き換えます
    • .info.yml の依存関係を更新します
    • コントローラー、ルート、ロジックをカスタマイズします
  3. 有効化してテストします:

    ddev drush en mymodule -y
    ddev drush cr
    
  4. 反復的に開発します:

    • 機能を実装します
    • キャッシュをクリアします:ddev drush cr
    • 十分にテストします
    • ログを確認します:ddev drush watchdog:tail
標準的な開発ワークフロー
  1. 計画: 必要な API/フックを特定します
  2. コーディング: Drupal API を使用して実装します
  3. テスト: モジュールを有効化し、キャッシュをクリアし、機能をテストします
  4. デバッグ: ログを確認し、必要に応じて Xdebug を使用します
  5. 改善: 最適化し、テストを追加し、コード品質を向上させます

ベストプラクティス

モジュール開発
  1. PSR-4 オートローディング: 名前空間の規約に従ってください
  2. 依存性注入: クラスでは DI を使用してください
  3. フック: .module ファイルにのみ実装してください
  4. 型ヒント: 適切な PHP の型宣言を使用してください
  5. ドキュメント: PHPDoc ブロックを追加してください
  6. テスト: 自動テストを作成してください
コード品質
  1. Drupal コーディング標準: PHPCS のルールに従ってください
  2. セキュリティ: 入力を検証し、出力をサニタイズし、権限を確認してください
  3. パフォーマンス: 可能な場合はキャッシュし、クエリを最適化してください
  4. アクセシビリティ: フォームとページがアクセシブルであることを確保してください
  5. 国際化: すべての文字列に $this->t() を使用してください
API の使用
  1. Entity API: 直接の DB クエリよりもエンティティ操作を優先してください
  2. Configuration: 設定には Config API を使用してください
  3. State API: 一時的またはエクスポート不要なデータに使用してください
  4. Cache API: 負荷の高い操作にはキャッシュを実装してください
  5. Queue API: 長時間実行されるタスクに使用してください

一般的なパターン

イベントサブスクライバー
class MyModuleSubscriber implements EventSubscriberInterface {
  public static function getSubscribedEvents() {
    return [KernelEvents::REQUEST => ['onRequest', 0]];
  }

  public function onRequest(RequestEvent $event) {
    // Handle event
  }
}
カスタム権限
# mymodule.permissions.yml
administer mymodule:
  title: 'Administer My Module'
  restrict access: true
カスタムアクセスチェック
class CustomAccessCheck implements AccessInterface {
  public function access(AccountInterface $account) {
    return AccessResult::allowedIf($account->hasPermission('access content'));
  }
}

トラブルシューティング

モジュールが表示されない
  • .info.yml の構文を確認してください
  • core_version_requirement を確認してください
  • キャッシュをクリアしてください: ddev drush cr
フックが動作しない
  • フック名が正しいことを確認してください
  • フックを追加した後はキャッシュをクリアしてください
  • フックの順序が重要な場合はモジュールの weight を確認してください
クラスが見つからない
  • PSR-4 名前空間がディレクトリと一致していることを確認してください
  • キャッシュをクリアしてクラスレジストリを再構築してください
  • composer dump-autoload でオートローディングを確認してください
データベースエラー
  • スキーマ定義の構文を確認してください
  • スキーマ変更後は ddev drush updb を実行してください
  • クエリ内のテーブル名・カラム名を確認してください

リソース

リファレンスドキュメント
  • references/hooks.md - 例付きの一般的なフック

    • エンティティフック
    • フォームフック
    • ノードフック
    • インストールフック
    • トークンフック
  • references/module_structure.md - モジュールのパターン

    • コントローラーとルーティング
    • フォーム(config とカスタム)
    • プラグイン(ブロック、フィールドなど)
    • サービスと DI
    • イベントサブスクライバー
アセットテンプレート
  • assets/module-template/ - モジュールのスキャフォールド
    • .info.yml メタデータ
    • .module フックファイル
    • .routing.yml ルート
    • コントローラーの例

バージョン互換性

Drupal 8 vs 9 vs 10 vs 11
  • コア API: バージョン間でほぼ一貫しています
  • PHP 要件: 8.x (7.0+)、9.x (7.3+)、10.x (8.1+)、11.x (8.3+)
  • 非推奨: アップグレード時は変更記録を確認してください
  • Symfony: Drupal の各バージョンで Symfony のバージョンが異なります

関連項目

  • drupal-frontend - テーマ開発、Twig テンプレート
  • drupal-tooling - DDEV と Drush の開発ツール
  • Drupal API - 公式 API ドキュメント

コメント