
もはやプログラミングは、AIに書かせる時代なのだそうです・・・。
そして、最近もてはやされている "Vibe(バイブ)コーディング" をkiroでやってみて、
未来のプログラミングを体験してみたいと思います。
Vibeコーディングとは?
もうすでに、仕事でAIコーディングやっている人は、釈迦に説法になりますが、
一言で説明すると「AIと対話しながらノリでプログラムを仕上げていく」と言うやり方です。
「バイブス」の意味と同じVibeですね。
まだ知らない人のために説明すると、Vibeコーディングは、以下のような特性があります。
- 雑な自然言語で方向性を渡す
- 完璧な仕様を書かない
- ノリと対話で形にしていく
- AIとのラリーで整えていく
仕様駆動のKiroでも、最初はあえてラフに始めることができるのも特徴ですね。
今回構築するモノ
基本中の基本として、LAMPをDockerでローカル起動できる、「掲示板」的なWebシステムを作ってみたいと思います。
下記の手順に沿って、作業を進めますね。
全体手順
1. Docker環境を用意
2. Kiroでプロジェクト生成
3. vibeで要件を投げる
4. 仕様を整える
5. 実装生成
6. 修正・改善
7. 起動確認
事前にプロジェクト用のフォルダを作って準備しておきます。
mkdir lamp_bbs
※GUIでフォルダを作ってもいいです。
このフォルダを、Kiroで開いた状態からスタートします。
1. Docker環境を用意
事前に作っておいたフォルダの中に以下の内容を準備します。
lamp-bbs/
docker-compose.yml
php/
Dockerfile
src/
※ファイルやフォルダは、基本的に空で問題ないです。後でKiroに書いてもらうので。
2. Kiroでプロジェクト生成
以下をプロンプトで入力します。
1. 基本指示をする
これからPHP + MySQLのLAMP構成で開発します。
ローカルではDockerを使用します。
フレームワークは使用しません。
シンプルなMVC構成で進めます。
ここでアーキテクチャなどの指示をしておくことで、勝手にLaravelやcomposerなどのフレームワークを入れられないようにします。
2. ディレクトリ方針を固定する
プロジェクト構成は以下を想定しています。
- docker-compose.yml
- php/Dockerfile
- src配下にアプリケーションコード
この前提で設計を考えてください。
プロジェクト構成図
.
├── docker-compose.yml # Docker環境定義
├── php/
│ ├── Dockerfile # PHPコンテナ設定
│ └── apache-config.conf # Apache設定
└── src/ # アプリケーションコード
├── config/ # 設定ファイル
│ └── config.php
├── core/ # MVCフレームワーク基底
│ ├── Controller.php
│ ├── Model.php
│ └── Database.php
├── controllers/ # コントローラー層
│ └── HomeController.php
├── models/ # モデル層(今後追加)
├── views/ # ビュー層
│ └── home/
│ └── index.php
└── public/ # 公開ディレクトリ
├── index.php # エントリーポイント
└── .htaccess # URL書き換え
この指示も、勝手に構成を決められるのを防ぐ事前設定です。
3. 設計モードであることを明示
まだ実装は不要です。
まずは全体設計の提案をしてください。
Kiroはすぐにコードを書きたがります。
まずは、書かせるのではなく、設計をちゃんと提示してもらうことが重要です。
すると、次のような質問が表示されます。
このプロジェクトの設計を進めるにあたり、要件から始めるか、技術設計から始めるか、どちらがよろしいですか?
1. 要件 [ Recommended ]
ビジネス要件やユースケースを整理してから技術設計に進む
2. 技術設計
技術的なアーキテクチャや実装方針から始めて、後で要件を整理する
おすすめ[Recommended]を選択するのがいいでしょう。
しばらく待つと、".kiro" と言うフォルダが作られて、"requirements.md"と言う要件定義書が作成されました。
# Requirements Document
## Introduction
このドキュメントは、PHP + MySQLのLAMP構成で動作するシンプルなMVCアーキテクチャの要件を定義します。フレームワークを使用せず、軽量で理解しやすい構造を提供し、Docker環境でのローカル開発をサポートします。
## Glossary
- **MVC_Framework**: Model-View-Controllerパターンを実装するコアシステム
- **Router**: HTTPリクエストを適切なControllerにマッピングするコンポーネント
- **Controller**: ビジネスロジックを処理し、ModelとViewを調整するコンポーネント
- **Model**: データベースとのやり取りを担当するコンポーネント
- **View**: HTMLレスポンスを生成するテンプレートコンポーネント
- **Database_Connection**: MySQLデータベースへの接続を管理するコンポーネント
- **Request**: HTTPリクエストを表現するオブジェクト
- **Response**: HTTPレスポンスを表現するオブジェクト
- **Configuration**: アプリケーション設定を管理するコンポーネント
## Requirements
### Requirement 1: ルーティング機能
**User Story:** As a developer, I want a simple routing system, so that I can map URLs to specific controllers and actions
#### Acceptance Criteria
1. WHEN an HTTP request is received, THE Router SHALL parse the URL path and HTTP method
2. WHEN a route matches the request, THE Router SHALL instantiate the corresponding Controller and invoke the specified action method
3. WHEN no route matches the request, THE Router SHALL return a 404 HTTP status code
4. THE Router SHALL support GET, POST, PUT, and DELETE HTTP methods
5. THE Router SHALL support dynamic URL parameters (e.g., /users/{id})
6. WHEN dynamic parameters are present, THE Router SHALL pass them to the Controller action method
### Requirement 2: コントローラー基盤
**User Story:** As a developer, I want a base controller class, so that I can easily create controllers with common functionality
#### Acceptance Criteria
1. THE MVC_Framework SHALL provide a base Controller class
2. THE Controller SHALL provide methods to render views with data
3. THE Controller SHALL provide methods to return JSON responses
4. THE Controller SHALL provide access to Request and Response objects
5. WHEN a controller action completes, THE Controller SHALL return an appropriate HTTP response
### Requirement 3: データベース接続管理
**User Story:** As a developer, I want a database connection manager, so that I can safely interact with MySQL
#### Acceptance Criteria
1. THE Database_Connection SHALL establish a PDO connection to MySQL using environment variables
2. THE Database_Connection SHALL use prepared statements for all queries
3. WHEN a database error occurs, THE Database_Connection SHALL throw a descriptive exception
4. THE Database_Connection SHALL support transaction management (begin, commit, rollback)
5. THE Database_Connection SHALL implement a singleton pattern to reuse connections
### Requirement 4: モデル基盤
**User Story:** As a developer, I want a base model class, so that I can perform common database operations easily
#### Acceptance Criteria
1. THE MVC_Framework SHALL provide a base Model class
2. THE Model SHALL provide methods for CRUD operations (create, read, update, delete)
3. THE Model SHALL use the Database_Connection for all database interactions
4. WHEN executing queries, THE Model SHALL use prepared statements to prevent SQL injection
5. THE Model SHALL support finding records by ID
6. THE Model SHALL support finding all records with optional filtering
### Requirement 5: ビューレンダリング
**User Story:** As a developer, I want a simple view rendering system, so that I can generate HTML responses with dynamic data
#### Acceptance Criteria
1. THE View SHALL load PHP template files from a designated views directory
2. WHEN rendering a view, THE View SHALL make provided data available as variables
3. THE View SHALL support layout templates for consistent page structure
4. WHEN a view file does not exist, THE View SHALL throw a descriptive exception
5. THE View SHALL automatically escape output to prevent XSS attacks by default
6. WHERE manual output is needed, THE View SHALL provide a method to render raw HTML
### Requirement 6: リクエスト処理
**User Story:** As a developer, I want to access request data easily, so that I can handle user input safely
#### Acceptance Criteria
1. THE Request SHALL provide access to GET parameters
2. THE Request SHALL provide access to POST parameters
3. THE Request SHALL provide access to request headers
4. THE Request SHALL provide access to the HTTP method
5. THE Request SHALL provide access to the request URI
6. THE Request SHALL sanitize input data to prevent common security vulnerabilities
### Requirement 7: レスポンス生成
**User Story:** As a developer, I want to control HTTP responses, so that I can send appropriate status codes and headers
#### Acceptance Criteria
1. THE Response SHALL allow setting HTTP status codes
2. THE Response SHALL allow setting response headers
3. THE Response SHALL support JSON response generation
4. THE Response SHALL support HTML response generation
5. THE Response SHALL support redirect responses with appropriate status codes
### Requirement 8: 設定管理
**User Story:** As a developer, I want centralized configuration management, so that I can easily manage application settings
#### Acceptance Criteria
1. THE Configuration SHALL load settings from environment variables
2. THE Configuration SHALL load settings from configuration files
3. THE Configuration SHALL provide database connection parameters
4. THE Configuration SHALL provide application-level settings (debug mode, timezone, etc.)
5. WHEN a required configuration value is missing, THE Configuration SHALL throw a descriptive exception
### Requirement 9: エラーハンドリング
**User Story:** As a developer, I want consistent error handling, so that I can debug issues and provide user-friendly error messages
#### Acceptance Criteria
1. WHEN an uncaught exception occurs, THE MVC_Framework SHALL log the error details
2. WHERE debug mode is enabled, THE MVC_Framework SHALL display detailed error information
3. WHERE debug mode is disabled, THE MVC_Framework SHALL display a generic error page
4. THE MVC_Framework SHALL support custom error handlers for different HTTP status codes
5. WHEN a database error occurs, THE MVC_Framework SHALL log the query and error message
### Requirement 10: オートローディング
**User Story:** As a developer, I want automatic class loading, so that I don't need to manually require files
#### Acceptance Criteria
1. THE MVC_Framework SHALL implement PSR-4 compliant autoloading
2. WHEN a class is referenced, THE MVC_Framework SHALL automatically load the corresponding file
3. THE MVC_Framework SHALL support a defined namespace structure
4. WHEN a class file cannot be found, THE MVC_Framework SHALL throw a descriptive exception
### Requirement 11: セッション管理
**User Story:** As a developer, I want session management, so that I can maintain user state across requests
#### Acceptance Criteria
1. THE MVC_Framework SHALL provide a Session wrapper class
2. THE Session SHALL start sessions automatically when needed
3. THE Session SHALL provide methods to set and get session data
4. THE Session SHALL provide methods to destroy sessions
5. THE Session SHALL provide flash message support for one-time messages
### Requirement 12: バリデーション機能
**User Story:** As a developer, I want input validation utilities, so that I can validate user input easily
#### Acceptance Criteria
1. THE MVC_Framework SHALL provide a Validator class
2. THE Validator SHALL support common validation rules (required, email, min length, max length, numeric)
3. WHEN validation fails, THE Validator SHALL return descriptive error messages
4. THE Validator SHALL support custom validation rules
5. THE Validator SHALL validate multiple fields and return all errors at once
3. vibeで要件を投げる
このステップでは、以下のような目的で進めます。
- 曖昧にゴールを伝える
- 機能の方向性を出させる
- まだ仕様は固めない
- AIの提案を引き出す
1. kiroへの命令
シンプルな掲示板を作りたいです。
投稿と一覧表示ができればOKです。
名前とメッセージを保存します。
最低限のセキュリティは考慮してください。
以下について提案して
- 機能一覧
- DBテーブル案
- ディレクトリ構成
- 処理フロー
- 必要ファイル一覧
以下のような提案が出てきました。
機能一覧
投稿機能(入力検証、保存、メッセージ表示)
一覧表示機能(新しい順、HTMLエスケープ)
セキュリティ機能(XSS/SQLインジェクション対策)
エラーハンドリング
DBテーブル案
posts (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
ディレクトリ構成
├── docker-compose.yml
├── php/Dockerfile
├── mysql/init.sql
└── src/
├── index.php
├── config/database.php
├── controllers/PostController.php
├── models/PostModel.php
├── views/post_view.php
└── public/css/style.css
処理フロー
一覧表示:
index.php → Controller → Model → DB → View
投稿作成:
フォーム送信 → 検証 → Model → DB → 成功/エラー表示
必要ファイル
Docker: docker-compose.yml, Dockerfile, init.sql
アプリ: index.php, Controller, Model, View
設定: database.php, .env
設計図
# 技術設計書 - シンプル掲示板アプリケーション
## 概要
本設計書は、PHP + MySQL (LAMP構成) で構築されるシンプルな掲示板アプリケーションの技術設計を定義します。フレームワークを使用せず、MVCパターンに基づいた構成で実装され、Docker環境で動作します。
ユーザーは名前とメッセージを投稿でき、投稿された内容が一覧表示されます。XSS対策とSQLインジェクション対策を実装し、セキュアなアプリケーションを実現します。
## 機能一覧
### 1. 投稿機能
- 名前とメッセージの入力フォーム表示
- 入力値の検証(必須チェック、文字数制限)
- データベースへの投稿保存
- 成功/エラーメッセージの表示
### 2. 投稿一覧表示機能
- データベースから投稿を新しい順に取得
- 投稿ID、名前、メッセージ、投稿日時の表示
- HTMLエスケープ処理によるXSS対策
- 投稿が存在しない場合のメッセージ表示
### 3. セキュリティ機能
- XSS対策(htmlspecialchars によるエスケープ)
- SQLインジェクション対策(プリペアドステートメント)
- 入力値の検証とサニタイゼーション
### 4. エラーハンドリング機能
- データベース接続エラーの処理
- データ保存エラーの処理
- ユーザーフレンドリーなエラーメッセージ表示
- サーバーログへのエラー記録
## アーキテクチャ
### システム構成
```
[ユーザー] <--> [Webブラウザ] <--> [Apache/PHP Container] <--> [MySQL Container]
|
[MVC Architecture]
|
+------------------+------------------+
| | |
[Controller] [Model] [View]
| | |
リクエスト処理 DB操作 HTML生成
```
### MVCパターン
- **Model (Post_Model)**: データベースとのやり取りを担当
- 投稿データの保存
- 投稿データの取得
- PDOを使用したデータベース接続
- **View (Post_View)**: プレゼンテーション層
- 投稿フォームの表示
- 投稿一覧の表示
- HTMLエスケープ処理
- **Controller (Post_Controller)**: ビジネスロジック層
- リクエストの処理
- 入力値の検証
- ModelとViewの仲介
### Docker構成
```
docker-compose.yml
├── web (PHP + Apache)
│ ├── ポート: 8080:80
│ ├── ボリューム: ./src -> /var/www/html
│ └── 依存: db
└── db (MySQL)
├── ポート: 3306
├── 環境変数: MYSQL_ROOT_PASSWORD, MYSQL_DATABASE
└── 初期化スクリプト: init.sql
```
## コンポーネントとインターフェース
### 1. Post_Controller
**責務**: リクエスト処理、入力検証、ModelとViewの調整
**メソッド**:
```php
class PostController {
private $model;
public function __construct(PostModel $model)
// 投稿一覧ページの表示
public function index(): void
// 投稿の作成処理
public function create(): void
// 入力値の検証
private function validateInput(string $name, string $message): array
}
```
**入力検証ルール**:
- 名前: 必須、最大255文字
- メッセージ: 必須、最大1000文字
- 前後の空白を削除
### 2. Post_Model
**責務**: データベース操作
**メソッド**:
```php
class PostModel {
private $pdo;
public function __construct(PDO $pdo)
// 全投稿を新しい順に取得
public function getAllPosts(): array
// 新規投稿を保存
public function createPost(string $name, string $message): bool
}
```
**データベース接続**:
- PDO (PHP Data Objects) を使用
- プリペアドステートメントによるSQLインジェクション対策
- エラーモード: PDO::ERRMODE_EXCEPTION
### 3. Post_View
**責務**: HTML生成、表示
**メソッド**:
```php
class PostView {
// 投稿フォームと一覧を表示
public function render(array $posts, string $message = '', string $error = ''): void
// HTMLエスケープ処理
private function escape(string $value): string
}
```
**エスケープ処理**:
- htmlspecialchars() 関数を使用
- フラグ: ENT_QUOTES(シングル・ダブルクォート両方)
- エンコーディング: UTF-8
### 4. Database接続クラス
**責務**: データベース接続の管理
```php
class Database {
// PDOインスタンスを取得
public static function getConnection(): PDO
}
```
**接続情報**:
- ホスト: 環境変数 DB_HOST
- データベース名: 環境変数 DB_NAME
- ユーザー名: 環境変数 DB_USER
- パスワード: 環境変数 DB_PASSWORD
## データモデル
### postsテーブル
| カラム名 | データ型 | 制約 | 説明 |
|---------|---------|------|------|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | 投稿ID |
| name | VARCHAR(255) | NOT NULL | 投稿者名 |
| message | TEXT | NOT NULL | 投稿メッセージ |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 投稿日時 |
**インデックス**:
- PRIMARY KEY (id)
- INDEX (created_at) - 新しい順の取得を高速化
**DDL**:
```sql
CREATE TABLE IF NOT EXISTS posts (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```
## ディレクトリ構成
```
simple-bulletin-board/
├── docker-compose.yml # Docker構成ファイル
├── php/
│ └── Dockerfile # PHPコンテナの設定
├── mysql/
│ └── init.sql # データベース初期化スクリプト
├── src/ # アプリケーションソースコード
│ ├── index.php # エントリーポイント
│ ├── config/
│ │ └── database.php # データベース接続設定
│ ├── controllers/
│ │ └── PostController.php # 投稿コントローラー
│ ├── models/
│ │ └── PostModel.php # 投稿モデル
│ ├── views/
│ │ └── post_view.php # 投稿ビュー
│ └── public/
│ └── css/
│ └── style.css # スタイルシート
└── .env # 環境変数(Gitには含めない)
```
## 処理フロー
### 1. 投稿一覧表示フロー
```
[ユーザー] -> [index.php]
|
v
[PostController::index()]
|
v
[PostModel::getAllPosts()]
|
v
[Database Query: SELECT * FROM posts ORDER BY created_at DESC]
|
v
[PostView::render($posts)]
|
v
[HTML出力(エスケープ済み)]
|
v
[ユーザーのブラウザに表示]
```
### 2. 投稿作成フロー
```
[ユーザー] -> [フォーム送信]
|
v
[PostController::create()]
|
v
[入力値検証]
|
+------+------+
| |
[検証OK] [検証NG]
| |
v v
[PostModel:: [エラー
createPost()] メッセージ]
| |
v |
[プリペアド |
ステートメント] |
| |
v |
[INSERT INTO |
posts] |
| |
+------+------+
|
v
[PostView::render()]
|
v
[成功/エラーメッセージ表示]
|
v
[投稿一覧を再表示]
```
### 3. エラーハンドリングフロー
```
[エラー発生]
|
v
[try-catch ブロック]
|
+-- [PDOException] -> [データベースエラー]
| |
| v
| [ログに記録]
| |
| v
| [ユーザーフレンドリーな
| メッセージを表示]
|
+-- [その他の例外] -> [一般的なエラー処理]
|
v
[ログに記録]
|
v
[一般的なエラー
メッセージを表示]
```
## 必要ファイル一覧
### 1. Docker関連ファイル
#### docker-compose.yml
- Webコンテナ(PHP + Apache)の定義
- DBコンテナ(MySQL)の定義
- ネットワーク設定
- ボリュームマウント設定
#### php/Dockerfile
- PHPベースイメージ(php:8.1-apache)
- PDO MySQL拡張のインストール
- Apache設定
#### mysql/init.sql
- postsテーブルの作成
- 初期データ(オプション)
### 2. アプリケーションファイル
#### src/index.php
- エントリーポイント
- ルーティング処理
- コントローラーの呼び出し
#### src/config/database.php
- Database接続クラス
- PDO接続の設定
- 環境変数の読み込み
#### src/controllers/PostController.php
- リクエスト処理
- 入力値検証
- ModelとViewの調整
#### src/models/PostModel.php
- データベース操作
- 投稿の取得・保存
#### src/views/post_view.php
- HTML生成
- 投稿フォーム
- 投稿一覧表示
- エスケープ処理
#### src/public/css/style.css
- スタイル定義
- レスポンシブデザイン
### 3. 設定ファイル
#### .env
- データベース接続情報
- 環境固有の設定
- Gitには含めない
#### .env.example
- .envのテンプレート
- Gitに含める
#### .gitignore
- .envファイルの除外
- ベンダーディレクトリの除外
## Correctness Properties
プロパティとは、システムのすべての有効な実行において真であるべき特性や動作のことです。本質的には、システムが何をすべきかについての形式的な記述です。プロパティは、人間が読める仕様と機械で検証可能な正確性の保証との橋渡しとなります。
### Property 1: 投稿データのラウンドトリップ
任意の有効な投稿データ(名前とメッセージ)に対して、データベースに保存してから取得した場合、元のデータと同等のデータ(名前、メッセージ、および自動生成されたIDと投稿日時を含む)が返されるべきである。
**検証: 要件 2.3, 2.4**
### Property 2: 必須フィールドの空検証
任意の必須フィールド(名前またはメッセージ)が空文字列または空白文字のみで構成される場合、コントローラーは検証エラーを返し、データは保存されないべきである。
**検証: 要件 1.5, 1.6**
### Property 3: 投稿の新しい順ソート
任意の投稿セットに対して、データベースから取得される投稿は、created_atフィールドの降順(新しい順)でソートされているべきである。
**検証: 要件 3.2**
### Property 4: 投稿表示の完全性
任意の投稿に対して、ビューでレンダリングされたHTMLには、その投稿の名前、メッセージ、投稿日時のすべてが含まれているべきである。
**検証: 要件 3.3, 3.4, 3.5**
### Property 5: XSS対策のエスケープ処理
任意のユーザー入力(名前またはメッセージ)に特殊文字(<, >, &, ', ")が含まれる場合、ビューでレンダリングされたHTMLでは、これらの文字が適切にエスケープされているべきである。
**検証: 要件 4.1, 4.2, 4.4**
### Property 6: SQLインジェクション対策
任意のユーザー入力にSQL構文(例: ' OR '1'='1)が含まれる場合、データベース操作は安全に実行され、SQLインジェクション攻撃が防がれるべきである。
**検証: 要件 5.3**
### Property 7: 入力値の最大長検証
任意のフィールド(名前は255文字、メッセージは1000文字)に対して、最大長を超える入力は検証エラーを返すべきである。
**検証: 要件 6.1, 6.2**
### Property 8: 入力値の空白削除
任意の入力値に対して、前後の空白文字が削除された状態で処理されるべきである。
**検証: 要件 6.5**
### Property 9: エラーログの記録
任意のエラーが発生した場合、詳細なエラー情報がサーバーログに記録されるべきである。
**検証: 要件 7.3**
### Property 10: コントローラーの仲介役割
任意のリクエストに対して、コントローラーはモデルからデータを取得し、ビューにデータを渡すべきである。
**検証: 要件 3.1, 9.7**
### Property 11: 有効な投稿の保存と成功メッセージ
任意の有効な投稿データ(名前とメッセージが両方とも入力されており、最大長以内)に対して、コントローラーはモデルを呼び出してデータを保存し、成功メッセージを返すべきである。
**検証: 要件 1.7, 1.8**
## エラーハンドリング
### エラーの種類と処理
#### 1. データベース接続エラー
**発生条件**:
- MySQLサーバーが起動していない
- 接続情報(ホスト、ユーザー名、パスワード)が不正
- ネットワークの問題
**処理**:
```php
try {
$pdo = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
error_log("Database connection error: " . $e->getMessage());
die("データベースに接続できません。しばらくしてから再度お試しください。");
}
```
**ユーザーへの表示**: 「データベースに接続できません。しばらくしてから再度お試しください。」
**ログ記録**: 詳細なエラーメッセージとスタックトレース
#### 2. データ保存エラー
**発生条件**:
- データベース制約違反
- ディスク容量不足
- テーブルロック
**処理**:
```php
try {
$stmt->execute([$name, $message]);
} catch (PDOException $e) {
error_log("Data insertion error: " . $e->getMessage());
return false;
}
```
**ユーザーへの表示**: 「投稿の保存に失敗しました。もう一度お試しください。」
**ログ記録**: SQLエラーコードとメッセージ
#### 3. 入力検証エラー
**発生条件**:
- 必須フィールドが空
- 最大文字数超過
**処理**:
```php
$errors = [];
if (empty($name)) {
$errors[] = "名前を入力してください。";
}
if (mb_strlen($name) > 255) {
$errors[] = "名前は255文字以内で入力してください。";
}
```
**ユーザーへの表示**: 具体的な検証エラーメッセージ
**ログ記録**: 不要(通常の動作)
#### 4. 予期しないエラー
**発生条件**:
- PHPの実行時エラー
- メモリ不足
- その他の例外
**処理**:
```php
try {
// アプリケーションロジック
} catch (Exception $e) {
error_log("Unexpected error: " . $e->getMessage());
die("エラーが発生しました。管理者に連絡してください。");
}
```
**ユーザーへの表示**: 「エラーが発生しました。管理者に連絡してください。」
**ログ記録**: 完全なスタックトレースとコンテキスト情報
### エラーログの設定
**php.ini設定**:
```ini
error_reporting = E_ALL
display_errors = Off # 本番環境
log_errors = On
error_log = /var/log/php/error.log
```
**カスタムログ関数**:
```php
function logError($message, $context = []) {
$timestamp = date('Y-m-d H:i:s');
$contextStr = json_encode($context);
error_log("[$timestamp] $message | Context: $contextStr");
}
```
### 環境別のエラー表示
**開発環境**:
- 詳細なエラーメッセージを画面に表示
- スタックトレースを表示
- display_errors = On
**本番環境**:
- ユーザーフレンドリーなメッセージのみ表示
- 詳細はログに記録
- display_errors = Off
## テスト戦略
### テストアプローチ
本プロジェクトでは、ユニットテストとプロパティベーステストの両方を使用して包括的なテストカバレッジを実現します。
- **ユニットテスト**: 特定の例、エッジケース、エラー条件を検証
- **プロパティベーステスト**: すべての入力に対する普遍的なプロパティを検証
両者は補完的であり、包括的なカバレッジに必要です。ユニットテストは具体的なバグを捕捉し、プロパティテストは一般的な正確性を検証します。
### プロパティベーステスト
**使用ライブラリ**: [Eris](https://github.com/giorgiosironi/eris) (PHPのプロパティベーステストライブラリ)
**設定**:
- 各プロパティテストは最低100回の反復を実行
- 各テストは設計書のプロパティを参照するタグを含む
- タグ形式: `@Feature: simple-bulletin-board, Property {番号}: {プロパティテキスト}`
**プロパティテストの例**:
```php
/**
* @Feature: simple-bulletin-board, Property 1: 投稿データのラウンドトリップ
*/
public function testPostRoundTrip() {
$this->forAll(
Generator\string(),
Generator\string()
)->then(function($name, $message) {
// 有効な入力に制限
$name = substr($name, 0, 255);
$message = substr($message, 0, 1000);
if (empty(trim($name)) || empty(trim($message))) {
return; // スキップ
}
// 保存
$id = $this->model->createPost($name, $message);
// 取得
$posts = $this->model->getAllPosts();
$savedPost = array_filter($posts, fn($p) => $p['id'] === $id)[0];
// 検証
$this->assertEquals($name, $savedPost['name']);
$this->assertEquals($message, $savedPost['message']);
});
}
```
### ユニットテスト
**使用フレームワーク**: PHPUnit
**テスト対象**:
#### 1. PostControllerのテスト
```php
class PostControllerTest extends TestCase {
// 有効な投稿の作成
public function testCreateValidPost()
// 空の名前でエラー
public function testCreateWithEmptyName()
// 空のメッセージでエラー
public function testCreateWithEmptyMessage()
// 最大長超過でエラー
public function testCreateWithTooLongName()
public function testCreateWithTooLongMessage()
// 空白のトリミング
public function testTrimWhitespace()
}
```
#### 2. PostModelのテスト
```php
class PostModelTest extends TestCase {
// データベース接続
public function testDatabaseConnection()
// 投稿の保存
public function testCreatePost()
// 投稿の取得(新しい順)
public function testGetAllPostsOrderedByDate()
// データベース接続エラー
public function testDatabaseConnectionError()
// データ挿入エラー
public function testDataInsertionError()
}
```
#### 3. PostViewのテスト
```php
class PostViewTest extends TestCase {
// フォーム要素の表示
public function testRenderFormElements()
// 投稿一覧の表示
public function testRenderPostList()
// 空の投稿リスト
public function testRenderEmptyPostList()
// HTMLエスケープ
public function testHtmlEscaping()
// XSS対策
public function testXssProtection()
}
```
#### 4. 統合テスト
```php
class IntegrationTest extends TestCase {
// 投稿作成から表示までのフロー
public function testCompletePostFlow()
// エラーハンドリング
public function testErrorHandling()
// 本番環境でのエラー表示
public function testProductionErrorDisplay()
}
```
### テストデータ
**有効なテストデータ**:
- 通常の名前とメッセージ
- 最大長の名前とメッセージ
- 日本語、英語、記号を含むデータ
**無効なテストデータ**:
- 空文字列
- 空白のみの文字列
- 最大長を超えるデータ
**エッジケース**:
- 特殊文字(<, >, &, ', ")
- SQL構文(' OR '1'='1)
- UTF-8マルチバイト文字
- 絵文字
### テストカバレッジ目標
- コードカバレッジ: 80%以上
- 分岐カバレッジ: 75%以上
- すべてのCorrectness Propertiesをテスト
### CI/CD統合
**GitHub Actions設定例**:
```yaml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Start Docker Compose
run: docker-compose up -d
- name: Run PHPUnit
run: docker-compose exec web vendor/bin/phpunit
- name: Run Property Tests
run: docker-compose exec web vendor/bin/phpunit --group property
```
## 実装の優先順位
### フェーズ1: 基本機能(必須)
1. Docker環境のセットアップ
2. データベース接続とPostModelの実装
3. PostControllerの基本実装
4. PostViewの基本実装
5. 投稿作成機能
6. 投稿一覧表示機能
### フェーズ2: セキュリティ(必須)
1. XSS対策の実装
2. SQLインジェクション対策の実装
3. 入力値検証の実装
### フェーズ3: エラーハンドリング(必須)
1. データベースエラーの処理
2. 入力検証エラーの処理
3. ログ記録の実装
### フェーズ4: テスト(推奨)
1. ユニットテストの作成
2. プロパティベーステストの作成
3. 統合テストの作成
### フェーズ5: 改善(オプション)
1. CSSスタイリングの改善
2. レスポンシブデザイン
3. パフォーマンス最適化
## 付録
### 環境変数の例
**.env**:
```
DB_HOST=db
DB_NAME=bulletin_board
DB_USER=app_user
DB_PASSWORD=secure_password_here
DB_ROOT_PASSWORD=root_password_here
```
### Composerの依存関係
**composer.json**:
```json
{
"require": {
"php": "^8.1"
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"giorgiosironi/eris": "^0.14"
}
}
```
### データベース初期化スクリプト
**mysql/init.sql**:
```sql
CREATE DATABASE IF NOT EXISTS bulletin_board CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE bulletin_board;
CREATE TABLE IF NOT EXISTS posts (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```
### セキュリティチェックリスト
- [ ] XSS対策: すべてのユーザー入力をエスケープ
- [ ] SQLインジェクション対策: プリペアドステートメントを使用
- [ ] 入力値検証: すべての入力を検証
- [ ] エラーハンドリング: 本番環境で詳細を非表示
- [ ] HTTPS: 本番環境でHTTPSを使用
- [ ] データベース権限: 最小権限の原則
- [ ] 環境変数: 機密情報を環境変数で管理
- [ ] ログ記録: すべてのエラーをログに記録
提案が薄かったら
以下のように、追い指示をしてあげましょう。
できるだけシンプルな構成でお願いします。
将来的な拡張は考えなくていいです。
制約を少し足す
JavaScriptは最小限で。
サーバーサイド中心で実装してください。
・・・こんな感じで、会話しながら、どんどん構築を進めていくのがいいでしょう。
気に入らない提案だったら作り直して貰えばいいし、構造を変更したかったら、そのまま指示すればいいだけなので、あとはプロンプトの書き方のコツが掴めたら、さほど難易度は高くないでしょう。
ちょっとしたコツとしては、「一気に作らない」「AIの設計センスを見る」「余計なモノを入れられていないかのチェック」などですね。
あと、あえて言うのであれば、仕様書や設計図などを読んで理解するエンジニアリングスキルは必須ですね。
4. 実装生成
いよいよコードを作らせるフェイズです。
もうすでに、kiroがコードを書き始めてしまっている場合は、一旦削除してもらうように指示おきましょう。
Dockerで動作する環境を生成してください。
条件:
- PHP8 + Apache
- MySQL8
- srcディレクトリをApacheのDocumentRootにマウント
- DB接続情報は環境変数で管理
まずは docker-compose.yml を生成してください。
まずは・・・と書くことで、1ファイルずつ進めることが出来ます。
次にPHP用のDockerfileを生成してください。
条件:
- PHP8系
- PDO MySQLを有効化
- Apache有効
- mod_rewrite不要
MySQL起動時にpostsテーブルを作成する
init.sqlを生成してください。
STEP4で確定したDB定義を使用してください。
一旦テスト
docker compose up -d
dockerを起動して、ちゃんとLAMP構成が出来ているか確認します。
ちゃんと動かない場合やエラーが出ている場合は、kiroに原因調査して、修正までしてもらいましょう。
アプリ生成
db.phpを生成してください。
条件:
- PDO使用
- 環境変数からDB情報取得
- 接続エラーは例外スロー
一覧+フォーム モジュールの生成
index.phpを生成してください。
条件:
- 投稿フォーム表示
- 投稿一覧表示(created_at DESC)
- htmlspecialchars使用
- デザインは最低限でOK
投稿処理
post.phpを生成してください。
条件:
- POSTのみ受け付け
- nameとmessageの未入力チェック
- PDOプリペアドステートメント使用
- 登録後はindex.phpへリダイレクト
表示テスト
docker compose restart
dockerで起動しているポートをブラウザで開いて、表示を確認してみます。
localhost:8080
なんともシンプルな掲示板が出来上がりました。
投稿してみると、ちゃんとデータが追加されていますね。
5. 修正・改善
AI開発で肝心なのは、ここからです。
出来上がった仕様やソースは、大抵の場合、想像していたものと少し違っていることが多いです。
それを修正するのがAI使いのポイントになります。
現状のシステム
- 投稿できる
- 一覧表示できる
- PDO使用済み
- XSS対策あり
- Dockerで動く
改善要望
1. CSRF対策を追加
2. バリデーション強化
3. 見た目を整える
4. ページネーション追加
5. データベースのマウント方式と起動高速化
1. CSRF対策を追加
CSRF対策を追加してください。
条件:
- セッションを使用
- トークンをフォームに埋め込む
- post.phpで検証
- 不正な場合はエラーメッセージ表示
ここでは、実装方針を固定して、何を使うかを指定します。
2. バリデーション強化
バリデーションを強化してください。
条件:
- nameは50文字以内
- messageは500文字以内
- エラーはindex.phpに表示
- 入力値は再表示する
次に、UX改善をして、実務っぽさ追加してもらいます。
AIに状態管理をやらせるのがポイントですね。
3. 見た目を整える
Bootstrap5を使用して
シンプルに見た目を整えてください。
デザインは最小限でOKです。
ロジックとUIを分離して改善するように指定して、変更の影響範囲を限定しておきます。
4. ページネーション追加
一覧表示にページネーションを追加してください。
条件:
- 1ページ10件
- GETパラメータでページ管理
- OFFSETとLIMIT使用
自分でつけると、まあまあめんどくさいページネーション機能をサクッと追加してもらいます。
5. データベースのマウント方式と起動高速化
Mysqlの起動を高速化とデータ永続化してください。
条件
- Mysqlのデータフォルダをsrc/data/mysqlで管理
- compose.yamlのvolumesでマウントする
dockerを再起動すると、データが消えていたので、dockerコンテナの中にデータが入っている状態でした。
起動するたびに、データベースを構築するのにも時間がかかるので、物理データをマウントする方式に変更してもらいます。
あとがき
Kiroを使って、こちらが1行もコードを書かずに、システム構築をしてみました。
デザインなどの細かな指定は、実際にまだまだ人間が行った方が早いし正確だとは思いますが、テンプレート的なものを用意したり、デザイン画像を作るなどすれば、対応できそうですね。
でも、システムが理解できない人だと、いいコード悪いコードなどの区別ができないし、どうやって命令して思った通りのシステムを作って貰えばいいかがなかなか難しいので、
人間側の、技術スキルが非常に重要であることもよく理解できましたね。
今後、プログラミングのコーディング方法は、AIによって大きく変わることが理解でき、それを体験できたので、ちょびっとずつ仕事で活用して、未来のプログラミングに備えたいと思います。
クレジットもまあまあサービスしてくれるKiroは無料でもそこそこ使えると言うこともわかったので、お試しで使ってもらうにも悪くないと思いますよ。
注意点としては、今回紹介したKiroプロンプトのまま命令しても、結果が違うことがあるかと思います。
都度軌道修正をしながら行うのが今の時点のAIプログラミングだと言うことをお伝えしておきます。
0 件のコメント:
コメントを投稿