SaaSのロジックがif ($tenant->plan === 'pro')のような条件から始まる場合、それは直接的な解決策に見えます。問題はカタログを2度目に変更したときに現れます。プラン名の変更、機能の個別販売、顧客への旧条件の維持、サポートによる一時的な有効化が発生します。すると商用名は安定したルールを表さなくなり、コントローラ、スケジュールタスク、クエリ、API、インターフェースに分散することになります。
PHP SaaSにおける機能管理では、商用オファーを検証可能なドメイン上の決定へ変換する必要があります。コードが問うべきなのは企業が「Pro」かどうかではなく、特定のアクションを実行できるか、どの上限で、どの条件下で、いつまで可能かです。この分離により、運用ルールを書き換えずに価格やパッケージを変更できます。
プラン、機能、上限、権限、設定を分離する

これらの概念は関連しますが、同じものではありません。プランは商用パッケージです。機能は、データのエクスポート、自動化の作成、連携の利用など、プロダクト上の可能性を有効にします。上限は、アクティブなプロジェクト数、課金対象ユーザー数、期間あたりのAPIリクエスト数など、許容される量や頻度を定義します。
権限は別の問いに答えます。つまり、企業内でどのアイデンティティがアクションを実行できるかです。組織にデータエクスポート機能があるからといって、すべてのユーザーがエクスポートできるわけではありません。最後に、顧客設定とは、選択したアイデンティティプロバイダー、保持ポリシー、通知テンプレートなど、特定の企業で有効な選択肢です。商用上の決定や認可を隠すために自由形式の設定を使うべきではありません。
- プラン: 権利と上限の商用上の構成。
- 機能: プロダクトの観点で表現される機能ルール。
- 上限: 機能またはリソースに紐づく定量可能な閾値。
- 権限: アクターがアクションを実行するための認可。
- 設定: すでに付与されたルールの範囲内で利用可能な動作パラメータ。
1つの決定にすべての層が必要になることがあります。自動化を作成するには、企業に対応する機能があり、アクティブな自動化の上限未満であり、ユーザーに管理権限が必要です。その後、フローで宛先設定を検証できます。
プラン名ではなくドメインルールをモデル化する
マーケティングから独立した技術識別子で、安定した機能カタログを維持します。たとえばautomation.create、data.export、api.webhooksです。カタログには、真偽値、整数、選択肢の集合、構造化ポリシーなど、期待する値の型を含められます。識別子はプロダクト上のニーズを表すものであり、プラン名やキャンペーン名を含めるべきではありません。
商用上の割り当ては別の層で解決できます。有効なプランは付与の集合を提供しますが、アドオン、レガシー移行、明示的な例外も存在し得ます。各企業に対する結果は、由来を持つ有効な権利の解決結果です。
機能: automation.create
有効値: true
由来: 自動化アドオン
有効期間: キャンセルまで
この由来は不可欠です。機能が有効な場合、プロダクト、サポート、請求は、それが現行プラン、レガシー条項、または有効期限付き例外のいずれに由来するかを知る必要があります。企業にplanフィールドだけを保存し、残りすべてを各利用箇所で推論することは避けてください。
単一の意思決定サービス
PHPでは、企業、機能、必要なコンテキストを受け取るEntitlementResolverやCapabilityGateなどのドメインサービスを公開します。単なる真偽値ではなく、説明可能な決定、すなわち許可または拒否、解決値、理由、元ルール、評価日時を返す必要があります。この日時は、リゾルバが決定した時点を表し、有効期間、期限切れ、後続するプラン変更を正しく解釈できます。コントローラ、コマンド、リスナー、非同期ワーカーはこのサービスを照会し、独自のサブスクリプションクエリを再構築しません。
実装前に測定可能な上限を定義する
曖昧な上限は、競合と実装エラーを生みます。「最大100ユーザー」であれば、何をユーザーとして数えるかに答える必要があります。保留中の招待、停止中のユーザー、サイクル中に削除されたメンバー、サービスアカウントは含むのでしょうか。「1,000件のエクスポート」では、期間、タイムゾーン、再試行、失敗したエクスポートがクォータを消費するかを定義する必要があります。
各上限について、少なくとも次を文書化してください。
- 計上するリソース、イベント、または消費量。
- スコープ: 企業、プロジェクト、ユーザー、または連携。
- ウィンドウ: 有効期間全体、暦日、請求月、または移動ウィンドウ。
- 制御時点: 作成前、有効化時、送信時、または集計後。
- 対応: ブロック、警告付き許可、キュー投入、機能低下、または承認要求。
- 並行実行、再試行、キャンセル、ロールバックの扱い。
アクティブなオブジェクト数の上限は通常、並行実行時に閾値超過を防ぐトランザクション操作または予約で検証します。消費量の上限には、明確なセマンティクスを持つカウンタと、イベントキーによる冪等性が必要です。インターフェースに表示するカウンタだけを信頼してはいけません。2つの同時リクエストが事前チェックを通過し、最大値を超える可能性があります。
また、警告とブロックを区別してください。80%時点のアラートは予測可能性を高めますが、リソースを作成または実行する箇所での実際の保護に代わるものではありません。
すべての実行経路でルールを適用する
ボタンを隠すことはUXの改善であり、アクセス制御ではありません。検証は、アクションを実行するサーバー側のユースケースに存在しなければなりません。これにより、Webインターフェース、公開API、連携、内部呼び出しをカバーできます。
非同期プロセスには追加の決定が必要です。キュー投入時に確認し、ジョブが遅延する可能性がある場合は実行時にも再確認します。この2つの時点の間に企業が機能を失った場合、ポリシーではジョブをキャンセルするのか、以前に受理されたため完了させるのか、レビューを要求するのかを定義する必要があります。選択は操作の種類に依存しますが、一貫して記録されなければなりません。
サポートおよび管理ツールは、黙ってルールを迂回すべきではありません。異なる管理権限で操作することはできますが、正式な付与、データ修正、例外的アクションのいずれを生成するのかを示し、トレーサビリティを残す必要があります。
プロダクトを分岐させずに変更、レガシー継承、例外を管理する
プラン変更は単なるラベル更新ではありません。現在の利用量を下回る上限への引き下げや、アクティブなプロセスを支える機能の撤回を伴う可能性があります。リソース種別ごとにポリシーを定義してください。新規作成を阻止して既存を維持する、超過分を明示的に無効化する、移行期間を設ける、企業管理者に選択を求める、といったものです。
一時的な例外は、スコープ、値、理由、発行者、有効期限を持つ第一級の付与であるべきです。is_vipのような手動フィールドは解釈が難しく、元の理由より長く残りがちです。レガシー顧客については、恒久的なコード分岐を作るのではなく、正確なルールとレビュー日を持つ移行割り当てをモデル化してください。
持続可能な例外とは、同じリゾルバが解釈する監査可能なデータです。危険な例外とは、特定のフローに追加された特別な条件分岐です。
機能、ロール、マルチテナント分離を組み合わせる
マルチテナントプラットフォームでは、権利、消費量、設定に関するすべてのクエリを正しい企業でスコープする必要があります。コンテキストをクライアント送信値だけから導出してはいけません。認証、要求されたドメイン、または検証済みの内部コンテキストから解決し、キュージョブやイベントへ伝播させます。
最終的な決定は通常、企業に機能があり、上限が使い尽くされておらず、アクターに必要な権限がある、という積集合です。機能の一元化はロールモデルの代替ではなく、ロールとプランが混在することを防ぎます。ロールは誰が自動化を管理するかを付与でき、機能は企業が自動化を利用できるかを決定します。
決定を説明可能にするデータ、監査、テスト
集約値だけでは不十分な場合、消費イベントとともに、有効期間と優先順位を持つ権利割り当てを保持してください。重要な決定を記録します。企業、アクターまたはプロセス、機能、評価値、結果、ソース、リクエストの相関関係です。これらの記録に不要な個人データを保存せず、義務に従って保持期間を設定してください。
監査では、過去のコードを読まなくても、アクションが拒否された理由に答えられる必要があります。これは商用変更、請求インシデント、サポート業務で特に有用です。
テストには、機能と値のマトリクス、正確な境界での上限、並行実行、プラン変更、例外の期限切れ、イベント再試行を含める必要があります。同じユースケースを共有する場合は、HTTP、API、キューワーカーを通じて同じケースを実行してください。ある企業が別の企業の権利を照会または消費できないことを確認するため、分離テストを追加します。
既存のPHPプラットフォームを一元化するための段階的計画
- コードと運用にあるプラン名、条件分岐、カウンタ、手動例外を棚卸しします。
- 影響の大きい機能または上限を1つ選び、移行前に完全なセマンティクスを定義します。
- まずは現行ソースと互換性を持つファサードとしてリゾルバを導入します。
- 適用箇所をインターフェースだけでなく中央のユースケースへ移します。
- 古い分岐を削除する前に決定を記録し、新しい動作と以前の動作を比較します。
- プランごとに明示的な割り当てへ移行し、ドメインから商用上の参照を取り除きます。
変更公開前のチェックリスト

- 機能には安定した識別子と曖昧さのないビジネス定義がありますか。
- 上限には単位、スコープ、期間、並行実行、超過時の対応が指定されていますか。
- ルールはサーバー、API、非同期プロセスで適用されていますか。
- ロール、機能、企業コンテキストは個別に検証されていますか。
- プラン変更と例外には有効期間、由来、監査がありますか。
- 上限境界、取り消し、マルチテナント分離のテストがありますか。
このモデルにより、商用カタログは、各変更が条件分岐の探索へ変わることなく進化できます。プラットフォームは、プロダクトとエンジニアリングの双方にとって理解可能で、測定可能かつ説明可能なルールを維持します。



