PHP Omikuji アーキテクチャ
システム概要
PHP Omikujiは、PHPエンジニア向けのおみくじアプリケーションです。伝統的な日本のおみくじをPHPプログラミングのテーマでアレンジし、運勢をPHPコードとして表示します。
アーキテクチャ図
システム全体構成
graph TB
subgraph "Client Side"
Browser[ブラウザ]
QRReader[QRコードリーダー]
end
subgraph "Docker Container"
subgraph "Nginx Container"
Nginx[Nginx<br/>Port: 8080]
end
subgraph "PHP-FPM Container"
Laravel[Laravel Application<br/>PHP 8.2]
end
subgraph "Redis Container"
Redis[Redis<br/>Cache & Session]
end
end
subgraph "Storage"
SQLite[(SQLite Database)]
FileSystem[File System<br/>Views/Assets]
end
Browser --> Nginx
QRReader --> Nginx
Nginx --> Laravel
Laravel --> Redis
Laravel --> SQLite
Laravel --> FileSystem
アプリケーション層構成
graph LR
subgraph "Presentation Layer"
Routes[Routes<br/>web.php]
Controller[OmikujiController]
Views[Blade Views<br/>- index<br/>- result<br/>- print]
end
subgraph "Business Layer"
Service[OmikujiService]
DataClass[Data Classes<br/>- FortuneData<br/>- FortuneMessages]
end
subgraph "Data Layer"
Models[Eloquent Models<br/>- Fortune<br/>- FortuneCategory<br/>- FortuneResult<br/>- LuckCategory<br/>- LuckDetail<br/>- FortuneLuckMapping]
Database[(SQLite)]
end
Routes --> Controller
Controller --> Service
Controller --> Views
Service --> DataClass
Service --> Models
Models --> Database
データベース構造
erDiagram
fortune_categories ||--o{ fortunes : has
fortune_categories ||--o{ fortune_luck_mappings : has
fortunes ||--o{ fortune_results : generates
luck_categories ||--o{ luck_details : contains
luck_categories ||--o{ fortune_luck_mappings : mapped_to
luck_details ||--o{ fortune_luck_mappings : mapped_by
fortune_categories {
bigint id PK
string key UK
string name
string description
decimal probability
integer sort_order
timestamps timestamps
}
fortunes {
bigint id PK
bigint fortune_category_id FK
text code
string description
timestamps timestamps
}
fortune_results {
bigint id PK
bigint fortune_id FK
string session_id UK
string ip_address
string user_agent
timestamps timestamps
}
luck_categories {
bigint id PK
string key UK
string name
string icon
integer sort_order
timestamps timestamps
}
luck_details {
bigint id PK
bigint luck_category_id FK
text message
integer message_index
timestamps timestamps
}
fortune_luck_mappings {
bigint id PK
bigint fortune_category_id FK
bigint luck_category_id FK
bigint luck_detail_id FK
timestamps timestamps
}
画面遷移図
stateDiagram-v2
[*] --> TOP画面
TOP画面 --> おみくじを引く : QRコードスキャン<br/>または<br/>「おみくじを引く」クリック
TOP画面 --> 印刷画面 : 「印刷用ページ」クリック
おみくじを引く --> 結果画面 : 自動リダイレクト<br/>(運勢抽選後)
結果画面 --> TOP画面 : 「もう一度引く」クリック
結果画面 --> Xシェア画面 : 「Xでシェア」クリック
結果画面 --> 結果画面 : 「実行」ボタンクリック<br/>(PHPコード実行アニメーション)
Xシェア画面 --> 結果画面 : ブラウザバック
印刷画面 --> TOP画面 : ブラウザバック
state "TOP画面 [/]" as TOP画面 {
QRコード表示
--
おみくじを引くボタン
--
印刷用ページリンク
}
state "おみくじを引く [/fortune]" as おみくじを引く {
運勢抽選処理
--
データベース保存
--
セッションID生成
}
state "結果画面 [/result/{key}]" as 結果画面 {
運勢表示
--
PHPコード表示
--
各種運勢詳細
--
実行ボタン
--
シェアボタン
}
state "印刷画面 [/print]" as 印刷画面 {
8枚のおみくじカード
--
印刷レイアウト
}
state "Xシェア画面 [外部]" as Xシェア画面 {
twitter.com/intent/tweet
}
画面詳細
graph TD
subgraph "1. TOP画面 [/]"
A1[QRコード<br/>大きく中央に表示]
A2[おみくじを引くボタン]
A3[印刷用ページリンク]
end
subgraph "2. おみくじ実行 [/fortune]"
B1[運勢を抽選]
B2[データベースに保存]
B3[セッションID生成]
end
subgraph "3. 結果画面 [/result/{key}]"
C1[運勢カテゴリ表示<br/>大吉・中吉など]
C2[PHPコード表示<br/>シンタックスハイライト付き]
C3[実行ボタン<br/>アニメーション機能]
C4[8つの運勢詳細<br/>カード形式で表示]
C5[Xシェアボタン]
C6[もう一度引くリンク]
end
subgraph "4. 印刷画面 [/print]"
D1[8枚のカードレイアウト]
D2[QRコード付き]
D3[切り取り線表示]
end
A1 -->|QRスキャン| B1
A2 -->|クリック| B1
A3 -->|クリック| D1
B3 -->|リダイレクト| C1
C6 -->|クリック| A1
C5 -->|外部リンク| E[X投稿画面]
リクエストフロー
sequenceDiagram
participant User
participant Browser
participant Nginx
participant Laravel
participant Service
participant Database
User->>Browser: QRコードをスキャン
Browser->>Nginx: GET /fortune
Nginx->>Laravel: リクエスト転送
Laravel->>Service: drawFortune()
Service->>Database: 運勢カテゴリ取得
Service->>Service: 確率に基づいて選択
Service->>Database: 運勢詳細取得
Service->>Database: 結果を保存
Database-->>Service: セッションID
Service-->>Laravel: FortuneResult
Laravel-->>Browser: リダイレクト /result/{key}
Browser->>Nginx: GET /result/{key}
Nginx->>Laravel: リクエスト転送
Laravel->>Service: getFortuneResult()
Service->>Database: 結果取得
Database-->>Service: 運勢データ
Service-->>Laravel: フォーマット済みデータ
Laravel-->>Browser: 結果画面表示
ディレクトリ構造
graph TD
Root[php-omikuji/]
Root --> App[app/]
Root --> Config[config/]
Root --> Database[database/]
Root --> Docker[docker/]
Root --> Public[public/]
Root --> Resources[resources/]
Root --> Routes[routes/]
App --> Controllers[Controllers/<br/>OmikujiController.php]
App --> Models[Models/<br/>6 Eloquent Models]
App --> Services[Services/<br/>OmikujiService.php]
App --> Data[Data/<br/>FortuneData.php<br/>FortuneMessages.php]
Database --> Migrations[migrations/<br/>テーブル定義]
Database --> Seeders[seeders/<br/>初期データ]
Docker --> DockerPHP[php/<br/>Dockerfile]
Docker --> DockerNginx[nginx/<br/>設定ファイル]
Resources --> Views[views/omikuji/<br/>- index.blade.php<br/>- result.blade.php<br/>- print.blade.php]
Resources --> Assets[css/ & js/]
Routes --> Web[web.php<br/>4つのルート定義]
主要コンポーネント
1. プレゼンテーション層
- OmikujiController: すべてのHTTPリクエストを処理
- Blade Views: 3つの画面(メイン、結果、印刷)
- Routes: 4つのエンドポイント
2. ビジネスロジック層
- OmikujiService: 運勢抽選のコアロジック
- 確率に基づく運勢選択
- セッションID生成
- 結果のフォーマット
3. データ層
- Eloquent Models: 6つのモデルでデータベースと連携
- SQLite Database: シンプルで可搬性の高いデータストレージ
4. インフラ層
- Docker: 開発・本番環境の統一
- Nginx: Webサーバー
- PHP-FPM: PHPアプリケーションサーバー
- Redis: キャッシュとセッション管理
技術スタック
- Backend: Laravel 12.x, PHP 8.2
- Frontend: Blade テンプレート, Tailwind CSS風のカスタムCSS
- Database: SQLite
- Cache: Redis
- Container: Docker, Docker Compose
- Web Server: Nginx
- その他: QRコード生成ライブラリ
特徴的な実装
1. PHPテーマの運勢: 運勢がPHPコードとして表示される
2. QRコード連携: イベント会場での配布を想定
3. 印刷機能: 物理的なおみくじカードの生成
4. VSCodeテーマUI: 開発者に親しみやすいダークテーマ
5. ソーシャルシェア: X(Twitter)への投稿機能
セキュリティ考慮事項
- セッションIDは16文字のランダム文字列
- SQLインジェクション対策(Eloquent ORM使用)
- XSS対策(Bladeテンプレートのエスケープ)
CSRF保護(Laravel標準)