このリポジトリには、Drupal 10 を用いた最小構成の ToDo アプリ が含まれています。
カスタムモジュール todo_app が todo コンテンツタイプと /todos 一覧ビューを提供し、PHPUnit による Functional テスト(TDD)でカバーされています。
| ツール | バージョン |
|---|---|
| Docker | 20.10+ |
| Docker Compose | v2.0+ |
ポート 8080 が空いていること。
リポジトリのルートで:
docker compose up -dコンテナが起動するまで 30 秒〜1 分ほど待ちます。状態確認:
docker compose ps期待する出力(両方 Up / healthy):
NAME IMAGE STATUS PORTS
drupal-db mariadb:10 Up (healthy) 3306/tcp
drupal-todo drupal:10-apache Up 0.0.0.0:8080->80/tcp
公式 Drupal イメージには Drush・PHPUnit・mysql クライアントが含まれないため、初回だけインストールします。
# mysql クライアント(drush が DB を扱うために必要)
docker compose exec drupal bash -c 'apt-get update -qq && apt-get install -y -qq default-mysql-client'
# drush
docker compose exec drupal composer require drush/drush --working-dir=/opt/drupal --no-interaction
# 開発用パッケージ(PHPUnit を含む)
docker compose exec drupal composer require --dev phpunit/phpunit drupal/core-dev:^10 \
--working-dir=/opt/drupal --no-interaction --with-all-dependencies⚠ このコマンドは 初回のみ 実行します。既にインストール済みの状態で再実行すると
AlreadyInstalledExceptionで失敗します。リセットしたい場合は §6「停止 / クリーンアップ」を参照してください。
docker compose exec drupal /opt/drupal/vendor/bin/drush site:install standard \
--db-url="mysql://drupal:drupal@db/drupal" \
--site-name="Drupal ToDo App" \
--account-name=admin \
--account-pass=admin \
--yes成功すると [success] Installation complete. と表示されます。
ブラウザで http://localhost:8080 を開く、または:
curl -sI http://localhost:8080 | head -1
# => HTTP/1.1 200 OK管理者でログイン: ユーザー admin / パスワード admin
docker compose exec drupal /opt/drupal/vendor/bin/drush en todo_app -y成功すると [success] Module todo_app has been installed. と表示されます。
このコマンドだけで以下が すべて自動で作成されます:
-
todoコンテンツタイプ -
field_status(Done / Not done) -
field_description(説明文) -
/todos一覧ビュー
| URL | できること |
|---|---|
| http://localhost:8080/todos | ToDo 一覧(タイトル + Done 状態) |
| http://localhost:8080/node/add/todo | ToDo を新規追加 |
| http://localhost:8080/node/1/edit | ID=1 の ToDo を編集(Done にチェック等) |
# 追加
docker compose exec drupal /opt/drupal/vendor/bin/drush ev '
$node = \Drupal\node\Entity\Node::create([
"type" => "todo",
"title" => "Buy milk",
"field_description" => "Get 1 liter from the store.",
"field_status" => 0,
"status" => 1,
]);
$node->save();
print "Saved nid=" . $node->id() . PHP_EOL;'
# 一覧
docker compose exec drupal /opt/drupal/vendor/bin/drush ev '
$nodes = \Drupal::entityTypeManager()
->getStorage("node")
->loadByProperties(["type" => "todo"]);
foreach ($nodes as $n) {
$done = (string) $n->get("field_status")->value === "1" ? "[x]" : "[ ]";
print "$done {$n->id()}: {$n->getTitle()}" . PHP_EOL;
}'
# Done に変更(nid=1 を完了にする)
docker compose exec drupal /opt/drupal/vendor/bin/drush ev '
$n = \Drupal\node\Entity\Node::load(1);
$n->set("field_status", 1)->save();
print "marked done" . PHP_EOL;'docker compose exec drupal bash -c '
mkdir -p /opt/drupal/web/sites/simpletest &&
chown -R www-data:www-data /opt/drupal/web/sites &&
chmod -R 777 /opt/drupal/web/sites/simpletest /tmp'docker compose exec -u www-data \
-e SIMPLETEST_BASE_URL=http://localhost \
-e SIMPLETEST_DB=mysql://drupal:drupal@db/drupal \
-e BROWSERTEST_OUTPUT_DIRECTORY=/tmp \
drupal bash -c 'cd /opt/drupal/web && ../vendor/bin/phpunit \
-c core/phpunit.xml.dist \
modules/custom/todo_app/tests/'期待される結果:
OK (6 tests, 30 assertions)
custom_modules/todo_app/tests/src/Functional/TodoAppTest.php に 6 つのケース:
-
testTodoContentTypeExists—todoコンテンツタイプが存在する -
testTodoHasStatusField—field_status(boolean)が存在する -
testTodoHasDescriptionField—field_description(text_long)が存在する -
testCanCreateTodo— Todo ノードを作成・保存できる -
testCanMarkTodoDone—field_statusを 1 に更新できる -
testTodosListViewExists— Viewtodosが存在し/todosで 200 を返す
docker compose stop再開:
docker compose startdocker compose down -v-v を付けないと named volumes(DB データ等)が残るので、完全リセットしたいときは必ず -v を付けます。
DB の起動を待ち切れていない可能性があります。30 秒待ってから再度アクセスしてください。
drupal-db の status が (healthy) になるまで待つのが確実です。
Drush は /opt/drupal/composer.json を見ます。コマンドの --working-dir=/opt/drupal を付け忘れていないか確認してください。
mysql クライアントがコンテナにインストールされていません。§2-1 のコマンドで導入してください:
docker compose exec drupal bash -c 'apt-get update -qq && apt-get install -y -qq default-mysql-client'既に Drupal がインストール済みの状態で drush site:install を再実行するとこのエラーになります。
- そのまま使う場合: 何もせず http://localhost:8080 にアクセス(既に動作中)
- 完全リセットしたい場合:
docker compose down -v # ボリュームごと削除 docker compose up -d # 起動し直し # その後、§2-1 と §2-2 を順に実行
ステップ 5-1 の chmod を実行してください。テストランナーは www-data で動作する必要があります(docker compose exec -u www-data を忘れずに)。
- そのノードは「公開済み(published)」か(編集画面の Published チェック)
- そのノードのコンテンツタイプは
todoか - キャッシュをクリア:
docker compose exec drupal /opt/drupal/vendor/bin/drush cr
モジュールの config/install/ の YAML を変更しても、既にインストール済みのサイトには反映されません。確実に反映するには:
docker compose exec drupal /opt/drupal/vendor/bin/drush pm:uninstall todo_app -y
docker compose exec drupal /opt/drupal/vendor/bin/drush en todo_app -y.
├── docker-compose.yml # Drupal 10 + MariaDB
├── handson.md # このファイル
├── CLAUDE.md # TDD グランドルール
└── custom_modules/
└── todo_app/
├── todo_app.info.yml # モジュール定義
├── config/install/
│ ├── node.type.todo.yml
│ ├── field.storage.node.field_status.yml
│ ├── field.field.node.todo.field_status.yml
│ ├── field.storage.node.field_description.yml
│ ├── field.field.node.todo.field_description.yml
│ ├── core.entity_form_display.node.todo.default.yml
│ ├── core.entity_view_display.node.todo.default.yml
│ └── views.view.todos.yml
└── tests/src/Functional/
└── TodoAppTest.php # PHPUnit Functional テスト
| 項目 | 値 |
|---|---|
| Drupal URL | http://localhost:8080 |
| 管理者 | admin / admin |
| DB ホスト | db(コンテナ内)/ コンテナ外からは未公開 |
| DB 名 | drupal |
| DB ユーザー | drupal / drupal |
| DB root | root / rootpw |
⚠ これはローカル開発用です。本番では絶対に使わないでください。