PullLog Backend は、個人のガチャ履歴を記録・管理する Web アプリ「PullLog」のバックエンド部分です。
フロントエンドとデータベースの間で API を通じたデータ中継を担い、リクエストに応じて JSON レスポンスを返します。
- バックエンドは Laravel + PostgreSQL を基盤技術としています
- 初期開発や検証のためのモック環境として MockAPI-PHP を利用しています
- 認証・セッション管理・統計処理・画像処理などを含みます
- RESTful API 形式で JSON レスポンスを返却
- ユーザー認証・トークン管理・CSRF セッションの検証
- ユーザーごとの履歴データの保存・集計
- 通貨単位・小数桁数に応じた課金データ処理
- 統計キャッシュによる効率的な分析処理
- 言語: PHP v8.3(開発環境 v8.4.2)
- フレームワーク: Laravel v12.20.0
- データベース: PostgreSQL v14.13(開発環境 v17.4)
- モック環境: MockAPI-PHP v1.3.1
- 画像処理: Intervention Image v3.11.4
- 開発用メール送信: mailtrap
主要テーブル(マイグレーション順):
| テーブル名 | 用途 | 主なカラム例 |
|---|---|---|
plans |
契約プラン管理 | id, name, max_apps, ... |
users |
ユーザー管理 | id, email, roles, plan_id, ... |
currencies |
通貨マスタ | code, name, minor_unit, rounding, ... |
apps |
アプリ管理 | id, app_key, currency_code, ... |
user_apps |
ユーザー・アプリ Pivot | id, user_id, app_id, ... |
auth_tokens |
認証トークン管理 | id, user_id, token, type, ... |
user_sessions |
CSRFトークンセッション管理 | csrf_token, user_id, email, ... |
stats_cache |
統計キャッシュ管理 | cache_key, user_id, value, ... |
logs |
ガチャ履歴管理(パーティション化) | (user_id, id), log_date, expense_amount, ... |
logs_with_money |
履歴ビュー(通貨換算済) | logs JOIN apps JOIN currencies |
logsテーブルはuser_idで ハッシュパーティション化 され、logs_p0~logs_p9を持ちます- Laravel/Eloquent からは代表テーブル
logsを通じて一元的にアクセスします - スキーマ定義は pulllog-ddl.sql を参照
erDiagram
users ||--o{ user_apps: "has"
users ||--o{ logs: "has"
users ||--o{ auth_tokens: "has"
users ||--o{ user_sessions: "has"
users ||--o{ social_accounts: "has"
users ||--o{ stats_cache: "has"
users }|--|| plans: "plan"
currencies ||--o{ apps: "has"
apps ||--o{ user_apps: "has"
apps ||--o{ logs: "has"
%% read-only view for analytics
users ||--o{ logs_with_money: "has"
apps ||--o{ logs_with_money: "has"
%% Mermaid ER (PostgreSQL oriented)
erDiagram
%% =======================
%% Users
%% =======================
users ||--o{ user_apps: "has"
users ||--o{ logs: "has"
users ||--o{ auth_tokens: "has"
users ||--o{ user_sessions: "has"
users ||--o{ social_accounts: "has"
users ||--o{ stats_cache: "has"
users }|--|| plans: "belongs to"
users {
SERIAL id
VARCHAR email
VARCHAR password
VARCHAR name
VARCHAR avatar_url
VARCHAR[] roles
INTEGER plan_id
TIMESTAMPTZ plan_expiration
VARCHAR language
theme theme
VARCHAR home_page
TIMESTAMPTZ last_login
VARCHAR last_login_ip
VARCHAR last_login_ua
BOOLEAN is_deleted
BOOLEAN is_verified
VARCHAR remember_token
INTEGER[] unread_notices
TIMESTAMPTZ email_verified_at
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
}
%% =======================
%% Plans
%% =======================
plans ||--o{ users: "has"
plans {
SERIAL id
VARCHAR name
TEXT description
INTEGER max_apps
INTEGER max_app_name_length
INTEGER max_app_desc_length
INTEGER max_log_tags
INTEGER max_log_tag_length
INTEGER max_log_text_length
INTEGER max_logs_per_app
INTEGER max_storage_mb
INTEGER price_per_month
BOOLEAN is_active
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
}
%% =======================
%% Currencies
%% =======================
currencies ||--o{ apps: "has"
currencies {
CHAR(3) code
VARCHAR name
VARCHAR symbol
VARCHAR symbol_native
SMALLINT minor_unit
NUMERIC rounding
VARCHAR name_plural
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
}
%% =======================
%% Apps
%% =======================
apps ||--o{ user_apps: "has"
apps ||--o{ logs: "has"
apps {
SERIAL id
VARCHAR(64) app_key
VARCHAR(128) name
VARCHAR(255) url
TEXT description
CHAR(3) currency_code "FK -> currencies.code"
VARCHAR(5) date_update_time
BOOLEAN sync_update_time
BOOLEAN pity_system
INTEGER guarantee_count
JSONB rarity_defs
JSONB marker_defs
JSONB task_defs
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
}
%% =======================
%% Pivot: user_apps
%% =======================
user_apps {
SERIAL id
INTEGER user_id "FK -> users.id"
INTEGER app_id "FK -> apps.id"
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
%% UNIQUE (user_id, app_id) 推奨
}
%% =======================
%% Logs (hash partitioned by user_id)
%% =======================
logs {
BIGSERIAL id
INTEGER user_id "FK -> users.id"
INTEGER app_id "FK -> apps.id"
DATE log_date
INTEGER total_pulls
INTEGER discharge_items
BIGINT expense_amount "minor units (non-negative)"
JSONB drop_details
JSONB tags
TEXT free_text
JSONB images
JSONB tasks
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
%% PRIMARY KEY (user_id, id)
%% UNIQUE (user_id, app_id, log_date)
%% PARTITION BY HASH (user_id)
}
%% =======================
%% View: logs_with_money (read-only)
%% =======================
users ||--o{ logs_with_money: "has"
apps ||--o{ logs_with_money: "has"
logs_with_money {
BIGINT id "from logs.id"
INTEGER user_id
INTEGER app_id
DATE log_date
INTEGER total_pulls
INTEGER discharge_items
BIGINT expense_amount
CHAR(3) currency_code
SMALLINT minor_unit
NUMERIC expense_decimal
JSONB drop_details
JSONB tags
TEXT free_text
JSONB images
JSONB tasks
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
%% VIEW: logs JOIN apps JOIN currencies
}
%% =======================
%% Auth tokens
%% =======================
auth_tokens {
SERIAL id
INTEGER user_id "FK -> users.id"
VARCHAR token
token_type type
VARCHAR code
BOOLEAN is_used
INTEGER failed_attempts
VARCHAR ip
VARCHAR ua
TIMESTAMPTZ expires_at
TIMESTAMPTZ created_at
}
%% =======================
%% User sessions
%% =======================
user_sessions {
VARCHAR csrf_token "PK"
INTEGER user_id "FK -> users.id"
VARCHAR email
TIMESTAMPTZ created_at
TIMESTAMPTZ expires_at
}
%% =======================
%% Social accounts
%% =======================
social_accounts {
SERIAL id
INTEGER user_id "FK -> users.id"
VARCHAR provider
VARCHAR provider_user_id
VARCHAR provider_email
VARCHAR avatar_url
TEXT access_token "encrypted cast"
TEXT refresh_token "encrypted cast"
TIMESTAMPTZ token_expires_at
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
}
%% =======================
%% Stats cache (per user or global when user_id NULL)
%% =======================
stats_cache {
INTEGER user_id "FK -> users.id (nullable)"
VARCHAR cache_key "PK"
JSONB value
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
}
- Git からソースを取得
.envファイルを配置し、APP_KEY・API_KEY を生成- Composer で依存関係をインストール
storage/bootstrap/cacheのパーミッション設定- Laravel マイグレーション実行後、DDL による
logsテーブルのパーティション作成 - 設定・ルートキャッシュの最適化
- Web サーバー(Nginx/Apache/VPS)の設定
https://api.pulllog.net/api/v1/dummyで JSON レスポンスが返却されることを確認
beta/ディレクトリ以下に配置php ./start_server.phpでローカル起動可能- フロントエンド
.env.localにモック API URL を指定すると開発時に接続可能 - メール認証機能など一部は簡略化されています
MAGIC METHODS に帰属します。
- Pull Request や Issue を歓迎します
- 設計や方針の議論は Discussions または Issue で行ってください
- セキュリティ関連の報告は一般の Issue ではなく、メール(
support@pulllog.net)にてお願いします