AnySpi.net解説

本資料は、私が個人開発として制作し実際に運営している
AnySpi.net を題材に、Laravel（PHP）での開発内容を
機能面・実装面を中心に具体的に共有することを目的としたものです。

守秘義務の関係上、業務案件での実際のお客様サイトや画面は開示できないため、
社内共有に支障のない形として、個人開発プロジェクトを用いて説明いたします。

以下では、AnySpi.netの画面スクリーンショットを1枚ずつ提示しながら、
それぞれの画面について、

・画面の役割／目的
・実装されている主な機能
・Laravelでの構成や設計上のポイント
・実装時に意識した点（拡張性・保守性・運用想定 等）

といった観点で解説しています。

単なる画面紹介ではなく、
どのような設計意図で、どのように実装したかが伝わる内容を意識していますので、
Laravelでの開発経験や、実務での再現性をご確認いただければ幸いです。

＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
## 制作背景
近年、日本における占い・スピリチュアル領域は、伝統的な対面鑑定や電話占いだけでなく、インターネットやスマートフォンを通じたサービス需要が大きく拡大しています。占いを含む関連サービス全体の市場規模は約 1兆円規模 と推計されており、オンライン占いやチャット占いの需要も増加傾向にあります。 ￼

10年前と比較した正確な統計データは公開情報として限定的ですが、スマートフォン普及や SNS の浸透により、占いサービスの形態は大きく変化しました。インターネットを介した占いサービスが一般化し、場所や時間を問わず利用可能な環境が整備されたことで、若年層を中心に市場全体の拡大に寄与していると考えられています。 ￼

しかしながら、現状のオンラインプラットフォームを見渡すと、占い師が単に出品しているだけでは収益につながりにくいという課題も顕在化しています。例えば、ココナラ、タイムチケット、TIPS、Stores など、占いサービスを出品できる場は多数存在しますが、多くのユーザーにとっては「知らない相手に対してお金を払って鑑定を依頼する」ことへの心理的ハードルが高く、購入につながりにくいという現実があります。また、SNS（Twitter や Instagram）で募集をかけている占い師も多いものの、実際の利用者からの反応が乏しいケースも見受けられます。

こうした状況を踏まえ、占い師自身が悩みや需要を把握しづらい現状と、一般ユーザーが安心して占いに触れられる機会が限定的である点に着目しました。AnySpi は、占い師がレビューを集めながら無料で占い体験を提供できる場として立案されたプラットフォームです。これは単なる出品の場ではなく、占い師とユーザーの信頼関係を育み、レビューを積み上げることで収益につなげやすい環境を提供することを目的としています。

この背景には、「単なるサービス出品ではマッチングが成立しにくい」という課題認識と、「占い師が実績を積みながらユーザーに安心感を与えられる仕組みが必要」という仮説がありました。AnySpi はこうした市場の変化と課題を受けて、占い体験の提供と信頼形成を両立させるプラットフォームとして設計されています。


## Laravel仕様
- Laravel 11.31
	- Laravel ui Ver 4.5
	- Bootstrap Ver 5.3
	- Tailwind2.2.19
シンプルにLaravel ui + Bootstrap 5.3を使用したかったので Viteは取り除いています。
現状トップページとなっているランディングページは Tailwind 2.2.19 を使用しています。

## DB設計
一覧表示や管理画面など、関連データをまとめて表示する箇所では
N+1 問題を避けるため、Eloquent の with() を用いた Eager Loading を適用しています。
特にユーザー一覧・レビュー一覧など、件数が増えやすい画面を対象に、
不要なクエリ発行を抑制する設計としています。

Controller にはリクエストの受け渡しと分岐処理のみを極力持たせ、
ビジネスロジックやクエリ条件は Models 側に集約することで、
FatController にならない構成を意識しています。

参考: ![DB構成図](DB_Table.png)
### users テーブル

ユーザー情報の中核となるテーブルであり、一般ユーザー・占い師・管理者を単一テーブルで管理しています。
is_reader / is_admin のフラグにより権限を判別するシンプルな構成とし、Role 管理を導入せずに運用コストを抑えています。

また、以下の点を考慮した設計としています。
	•	invite カラムにより、ユーザーごとの紹介コードを一意に管理
	•	points は現在の残高のみを保持し、履歴は別テーブルで管理
	•	login_streak / last_login_date により、ログインボーナスの判定を効率化

### partners テーブル

相性占いや複数人相談を想定し、ユーザーが「相談相手」を複数登録できる設計としています。
ユーザー本体（users）とは 1:N の関係とし、相談内容に依存する情報を users テーブルに持たせないことで、将来的な拡張性を確保しています。

### reviews テーブル

占い結果に対するレビューを管理するテーブルです。
	•	user_id：相談者（レビュー投稿者）
	•	reader_id：占い師（users テーブルを参照）
	•	is_public により、公開・非公開レビューを制御

同一 users テーブルを参照しつつ、役割（相談者／占い師）を外部キーで明確に分けることで、データ構造を単純化しています。

### review_reports テーブル

レビューに対する通報を管理するテーブルです。
通報者・対象レビュー・状態（pending / approved / rejected）を分離して管理することで、管理者による確認・対応フローを想定した設計としています。

レビュー本体とは独立したテーブルとすることで、通報機能の追加・変更がレビュー機能に影響しない構成としています。

### login_bonus_logs テーブル

ログインボーナスの付与履歴を管理するテーブルです。
user_id と login_date の組み合わせをユニークとすることで、同一日の重複付与を DB レベルで防止しています。

アプリケーション側の判定に依存せず、DB制約で不正・事故を防ぐ設計としています。

### inviters テーブル

紹介機能の成立履歴を管理するテーブルです。
	•	inviter_id：紹介したユーザー
	•	invitee_id：紹介されたユーザー
	•	points_awarded：付与ポイント

紹介コード自体は users テーブルで管理し、成立情報のみを本テーブルで保持することで、責務を明確に分離しています。

現状では (inviter_id, invitee_id) のユニーク制約は設けていませんが、運用フェーズに応じて追加可能な構成としています。

⸻

### settings テーブル

システム全体で共有される設定値を管理するテーブルです。
key / value 形式とし、ログインボーナス設定など、コード変更を伴わない運用調整を可能としています。

ユーザーに紐づかない全体設定のため、users テーブルとは直接リレーションを持たせていません。

### 総括（設計方針）

本DB設計では、
	•	小規模〜中規模運用を前提とした シンプルな正規化
	•	履歴・ログ系は独立テーブルで管理
	•	不正・重複が起きやすい箇所は DB制約で担保

という方針を採用しています。

MVP段階での実装・運用コストを抑えつつ、
要件拡張時には段階的に強化できる構成としています。

## Login仕様
本システムでは、以下の3種類のユーザーがログイン可能な構成としています。
	•一般ユーザー
	•占い師（一般ユーザー権限を兼ねる）
	•管理者

本件では複雑な権限確認を必要とせず、現時点の要件ではユーザー種別も
「一般ユーザー／占い師／管理者」に限定されています。
Scrum に基づくアジャイル開発の考え方を踏まえ、MVPとしての価値提供に直接寄与しない機能は初期実装では最小化する方針とし、
roles / permissions テーブルによる Role 管理は過剰な実装になると判断しました。
そのため users テーブルのフラグ管理（is_admin / is_reader）を採用し、
権限要件が追加された場合にはスプリント単位で Role 管理へ移行可能な構成としています。

users テーブルに以下のカラムを設け、
Boolean 判定によるシンプルな権限管理を行っています。
	•is_admin
	•is_reader

これにより、不要なテーブルや処理を増やさず、
要件に対して過不足のない構成としています。

## 未知のエラー対策
参考: ![エラー通知](error.jpg)
想定外の例外については、Laravel の Exception Handler を起点として Notification と連携し、即時にエラー通知が行われる構成としています。
なお、個人開発のため通知先は LINE Messaging API を用いて開発者本人の LINE に送信される設計とし、障害の早期検知と即時対応を可能にしています。

## 友人紹介ポイント付与
参考: ![ポイント付与コード](invite.jpg)
7.png（友人紹介）で紹介している招待URLの取り扱いは、内部的には InviteController で受け付けています。
個人開発の初期段階では実装コストを優先し、成立判定・二重付与防止・認証完了後の付与などは最小構成で実装しました。
現在は運用を通じて改善点が明確になっており、
(1) DBのユニーク制約による二重付与防止
(2) セッション上書きの抑止
(3) メール認証完了時の後追い付与（イベント連携）を優先度高で順次反映する方針です。

## スクリーンショット画像説明
1. ランディングページ
2. ログイン
3. ログイン後 Home画面
4. 占い師一覧
5. 占い師プロフィール
6. 右上ユーザーメニュー解放(Admin権限)
7. 友人紹介
8. ユーザープロフィール設定
9. ポイント履歴
10. ログインボーナスカレンダー
11. お相手情報登録
12. 占い師プロフィール設定
13. 占い師ダッシュボード

## 管理者ページ説明
- admin1 管理者専用ダッシュボード
- admin2 ポイント付与設定
- admin3 登録ユーザー一覧
- admin4 ユーザーポイント一覧
- admin5 ユーザーポイント編集
- admin6 全体メール送信
- admin7 メールフッター署名設定

# 各ページ機能解説
- ![ランディングページ](1.png)
	- ランディングページは 占い師がレビューを貰えて再掲載可能と言う条件を元に「占い師」の勧誘を最優先としたランディングページにしました。
- ![ログインページ](2.png)
	- ログインページはLaravel uiのデフォルトを使用しています。
- ![ユーザーホーム](3.png)
	- ユーザーホームは初めてのユーザーでもわかりやすいようにメインとなるメニューはショートカットの意味も含めて、メインカラムに出しています。
- ![占い師一覧](4.png)
	- 占い師一覧ページでは、上部に配置した絞り込み検索を開閉できる仕様としており、
	- タロットや四柱推命などの占術条件を必要に応じて指定し、好みの占い師を効率的に探せるようにしています。
- ![占い師プロフィール](5.png)
	- 占い師プロフィールページでは、対応可能な占術やレビュー実績を掲載し、自己紹介を含めて、ユーザーが「この人に占ってもらいたい」と判断しやすい構成としています。
- ![右上のユーザーメニュー](6.png)
	- 右上のユーザーメニューでは、ユーザーがワンタップで目的のページへ遷移できるよう、必要な項目を一覧表示しています。
	- 鑑定者メニューは鑑定者登録を完了したユーザーのみ表示され、管理者メニューは管理者権限（Admin）を持つユーザーにのみ表示される仕様としています。
- ![友人紹介](7.png)
	- 友人紹介機能では、紹介用URLをコピーする方法に加え、X（x.com）の紹介ボタンを押すことで、Xの投稿画面が立ち上がり、あらかじめ用意した AnySpi の紹介文が自動入力された状態でツイートできる仕組みとしています。

	- 紹介用URLは専用のランディングページで管理しており、クリック数および実際に登録に至ったかどうかまでを記録しています。

	- また、URLに付与される invite= パラメータを気にするユーザーへの配慮として、該当パラメータが存在する場合は Cookie に保存した上でリダイレクトを行い、最終的には anyspi.net/ のパラメータなしのURLを表示する仕様としています。

	- 紹介用URLパラメータは 新規登録した際に 自動的に任意の文字列が生成される仕組みになっています。
- ![プロフィール設定](8.png)
	- 一般ユーザーのプロフィール設定ページでは、占いに必要な生年月日をはじめ、自己紹介や希望する鑑定スタイルなどを登録できるようにしています。
	- 占い師は鑑定依頼があった場合にユーザーのプロフィールを閲覧できますが、一般ユーザー同士ではプロフィールを閲覧できない仕様としています。
- ![ポイント履歴](9.png)
	- ユーザーが各種アクションを行うたびに無料ポイントを獲得できる仕組みを採用しています。
	- ゲーミフィケーションの要素を取り入れることで、毎日のログインや新しい占い師との出会いを促進しています。
- ![ログインカレンダー](10.png)
	- ログインカレンダーでは、今後獲得予定のポイントをあらかじめ表示し、
	- 「明日ログインすると何ポイントもらえるか」を明確にすることで、透明性を重視した設計としています。
	- これにより、ゲーミフィケーション要素と継続利用への期待感を高めています。
- ![お相手登録](11.png)
	- お相手登録機能では、相性占いや三角関係などの相談を想定し、
	- ユーザーが複数人のお相手を自由に登録できる仕組みとしています。
- ![鑑定者プロフィール](12.png)
	- 鑑定者プロフィールを設定すると鑑定者として登録される仕組みです is_reader が Trueになります。
- ![占い師ダッシュボード](13.png)
	- 占い師ダッシュボードでは、自身の鑑定実績や鑑定結果に容易にアクセスできる構成としています。また、受付停止機能を備えており、占い師登録後も休業日を柔軟に設定できるようにしています。

# 管理者ページ解説
- ![管理者ダッシュボード](admin1.png)
	- 管理者ダッシュボードは、ユーザー管理テーブルの is_admin が true のユーザーにのみ表示されるページです。
	- 管理者ページでは、ユーザー数の把握やポイントの編集などを一目で確認・管理できる構成としています。
- ![ポイント付与設定](admin2.png)
	- ユーザーアクションに対するポイント付与設定のページです。
	- ここから簡単にユーザーに付与するポイントを設定できます。
- ![ユーザー一覧](admin3.jpg)
	- ユーザー一覧では ユーザーのポイント数やログイン状況 個別メール送信などの機能も備えています。
- ![ポイント編集](admin4.jpg)
	- トラブルがあった際に備えて管理者が手動でポイントを操作出来る仕組みになっています。
- ![個別ポイント編集画面](admin5.jpg)
	- 個別ポイント編集画面では、管理者権限によりユーザーのポイント数を編集できます。
	- 不正や恣意的な変更を防ぐため、変更時には理由の入力を必須とし、その内容はユーザーダッシュボードのポイント履歴から確認できる仕様としています。
- ![一斉メール送信](admin6.png)
	- ユーザーへ一斉にメール送信できる管理画面を用意しており、送信対象を「一般ユーザー」「占い師」「両方」から選択して配信できる仕様としています。
	- また、差し込み機能を備えており、{名前} などのタグを指定することで、ユーザー名を自動的に差し込んだメール送信が可能です。
- ![メール設定](admin7.png)
	- メール設定では、管理者パネルから送信するメールに対して、あらかじめ設定したフッターが自動で付与される仕様としています。
	- これにより、管理者は件名と本文のみを記載すればよく、毎回署名を意識する必要がありません。


