Перейти к содержимому
DedicatedPHP Контакт

Возможности и лимиты в PHP SaaS без условий по тарифам

Проектируйте возможности, лимиты и проверяемые исключения в PHP SaaS, чтобы коммерческие тарифы не расползались по условным операторам.

Редакционная диаграмма возможностей, лимитов, разрешений и централизованных правил для PHP SaaS-платформы нескольких компаний

Когда логика SaaS начинается с условий вроде if ($tenant->plan === 'pro'), это кажется прямым решением. Проблема возникает при втором изменении каталога: тариф переименовывают, возможность продаётся отдельно, клиент сохраняет прежние условия или поддержке нужно временно что-то включить. Тогда коммерческое название перестаёт описывать стабильное правило и оказывается распределённым между контроллерами, запланированными задачами, запросами, API и интерфейсом.

Управление возможностями в PHP SaaS должно переводить коммерческое предложение в проверяемые решения домена. Код не должен спрашивать, является ли компания «Pro», а должна ли она выполнить конкретное действие, с каким лимитом, на каких условиях и до какого времени. Такое разделение позволяет менять цены или состав пакетов без переписывания операционных правил.

Разделяйте тариф, возможность, лимит, разрешение и конфигурацию

Разделяйте тариф, возможность, лимит, разрешение и конфигурацию — guía visual de DedicatedPHP

Эти понятия связаны, но не взаимозаменяемы. Тариф — это коммерческий пакет прав и лимитов. Возможность открывает функциональность продукта, например экспорт данных, создание автоматизаций или использование интеграции. Лимит определяет допустимое количество или частоту, например активные проекты, тарифицируемых пользователей или API-запросы за период.

Разрешение отвечает на другой вопрос: какая идентичность может выполнить действие внутри компании. То, что организация обладает возможностью экспортировать данные, не означает, что экспортировать их может любой пользователь. Наконец, конфигурация клиента — это доступные для конкретной компании параметры, такие как выбранный провайдер идентификации, политика хранения или шаблон уведомлений. Не следует использовать свободную конфигурацию, чтобы скрывать коммерческие решения или решения об авторизации.

  • Тариф: коммерческий состав прав и лимитов.
  • Возможность: функциональное правило, выраженное в терминах продукта.
  • Лимит: измеримый порог, связанный с возможностью или ресурсом.
  • Разрешение: авторизация субъекта на выполнение действия.
  • Конфигурация: параметр поведения, доступный в рамках уже предоставленных правил.

Для решения могут потребоваться все уровни. Чтобы создать автоматизацию, компании нужна соответствующая возможность, она должна находиться ниже лимита активных автоматизаций, а пользователь должен иметь разрешение на администрирование. Затем поток может проверить конфигурацию назначения.

Моделируйте правила домена, а не названия тарифов

Поддерживайте стабильный каталог возможностей с техническими идентификаторами, независимыми от маркетинга: automation.create, data.export или api.webhooks. Каталог может включать ожидаемый тип значения: boolean, целое число, набор вариантов или структурированную политику. Идентификатор выражает потребность продукта; он не должен содержать название тарифа или кампании.

Коммерческое назначение можно разрешать на отдельном уровне. Действующий тариф предоставляет набор прав, но также могут существовать дополнения, унаследованные миграции и явные исключения. Результатом для каждой компании является разрешение эффективных прав с указанием происхождения.

возможность: automation.create
эффективное значение: true
происхождение: дополнение для автоматизаций
срок действия: до отмены

Это происхождение критически важно. Если возможность активна, продукту, поддержке и биллингу необходимо знать, исходит ли она из текущего тарифа, унаследованного условия или исключения с датой истечения. Не ограничивайтесь хранением одного поля plan у компании и выводом всего остального в каждой точке использования.

Единый сервис принятия решений

В PHP предоставьте сервис домена, например EntitlementResolver или CapabilityGate, который получает компанию, возможность и необходимый контекст. Он должен возвращать объяснимое решение, а не только boolean: разрешено или отклонено, разрешённое значение, причина, исходное правило и дата оценки. Эта дата представляет момент, в который резолвер определил решение, и позволяет корректно интерпретировать сроки действия, истечения и последующие изменения тарифа. Контроллеры, команды, listeners и асинхронные workers обращаются к этому сервису; они не воссоздают собственные запросы к подписке.

Определите измеримые лимиты до их реализации

Неоднозначный лимит порождает конфликты и ошибки реализации. «До 100 пользователей» требует ответить, кто считается пользователем: ожидающий приглашения, приостановленный, участник, удалённый в течение цикла, сервисная учётная запись? «Тысяча экспортов» требует определить период, часовой пояс, повторные попытки и то, расходует ли квоту неудачный экспорт.

Для каждого лимита задокументируйте как минимум:

  • Ресурс, событие или потребление, которое учитывается.
  • Область действия: компания, проект, пользователь или интеграция.
  • Окно: общий срок действия, календарный день, расчётный месяц или скользящее окно.
  • Момент контроля: до создания, при активации, при отправке или после консолидации.
  • Реакцию: заблокировать, разрешить с предупреждением, поставить в очередь, деградировать или потребовать одобрения.
  • Обработку конкурентного доступа, повторных попыток, отмен и отката.

Лимиты активных объектов обычно проверяются транзакционной операцией или резервированием, которое предотвращает превышение порога при конкурентном доступе. Лимитам потребления нужен счётчик с ясной семантикой и идемпотентностью через ключ события. Не полагайтесь только на счётчик, отображаемый в интерфейсе: два одновременных запроса могут пройти предварительную проверку и превысить максимум.

Также различайте предупреждение и блокировку. Оповещение на уровне 80 % повышает предсказуемость, но не заменяет реальную защиту в точке создания или выполнения ресурса.

Применяйте правила во всех путях выполнения

Скрыть кнопку — это улучшение пользовательского опыта, а не контроль доступа. Проверка должна существовать в серверном use case, который выполняет действие. Так она охватывает веб-интерфейс, публичный API, интеграции и внутренние вызовы.

Асинхронные процессы требуют дополнительного решения: проверять при постановке в очередь и повторно проверять при выполнении, если работа может задержаться. Если компания теряет возможность между этими моментами, политика должна определить, отменяется ли задача, завершается ли она, поскольку была принята ранее, или требует проверки. Выбор зависит от типа операции, но должен быть последовательным и зафиксированным.

Инструменты поддержки и администрирования не должны молча обходить правила. Они могут работать с отдельной административной авторизацией, но должны оставлять трассируемость и указывать, создают ли они формальное предоставление права, исправление данных или исключительное действие.

Управляйте изменениями, наследованием и исключениями без разветвления продукта

Изменение тарифа — это не только обновление метки. Оно может снизить лимит ниже текущего использования или отозвать возможность, поддерживающую активные процессы. Определите политики по типу ресурса: запретить новые создания и сохранить существующее, явно отключить превышения, предоставить переходный период или запросить выбор у администратора компании.

Временные исключения должны быть первоклассными предоставлениями прав с областью действия, значением, причиной, выдавшей стороной и сроком истечения. Ручное поле вроде is_vip трудно интерпретировать, и оно обычно переживает исходную причину. Для унаследованных клиентов моделируйте назначение миграции с точными правилами и датой пересмотра вместо создания постоянных ветвей кода.

Устойчивое исключение — это проверяемые данные, которые интерпретирует тот же резолвер; опасное исключение — специальное условие, добавленное в конкретный поток.

Сочетайте возможности, роли и изоляцию нескольких компаний

На платформе для нескольких компаний каждый запрос прав, потребления и конфигурации должен быть ограничен правильной компанией. Не выводите контекст только из значений, отправленных клиентом. Разрешайте его из аутентификации, запрошенного домена или проверенного внутреннего контекста и передавайте в задания очереди и события.

Итоговое решение обычно представляет собой пересечение: компания располагает возможностью, лимит не исчерпан, а субъект обладает требуемым разрешением. Централизация возможностей не заменяет модель ролей; она не допускает смешения ролей и тарифов. Роль может предоставлять кому разрешено администрировать автоматизации, тогда как возможность определяет, может ли компания использовать автоматизации.

Данные, аудит и тесты, позволяющие объяснять решения

Храните назначения прав со сроком действия и приоритетом вместе с событиями потребления, когда агрегата недостаточно. Регистрируйте значимые решения: компанию, субъекта или процесс, возможность, оценённое значение, результат, источник и корреляцию запроса. Не сохраняйте в этих записях ненужные персональные данные и установите хранение в соответствии со своими обязательствами.

Аудит должен отвечать, почему действие было отклонено, не вынуждая читать исторический код. Это особенно полезно при коммерческих изменениях, инцидентах биллинга и операциях поддержки.

Тесты должны включать матрицу возможностей и значений, лимиты на точной границе, конкурентный доступ, изменения тарифов, истечение исключений и повторные попытки событий. Выполняйте одни и те же сценарии через HTTP, API и workers очереди, когда они используют общий use case. Добавьте тесты изоляции, чтобы подтвердить, что одна компания не может запрашивать или потреблять права другой.

Постепенный план централизации существующей PHP-платформы

  1. Инвентаризируйте названия тарифов, условия, счётчики и ручные исключения в коде и операциях.
  2. Выберите возможность или лимит с высоким влиянием и определите его полную семантику до миграции.
  3. Внедрите резолвер как фасад, первоначально совместимый с текущими источниками.
  4. Перенесите точки применения в центральный use case, а не только в интерфейс.
  5. Регистрируйте решения и сравнивайте новое поведение с прежним до удаления старых ветвей.
  6. Мигрируйте тариф за тарифом к явным назначениям и удаляйте коммерческие ссылки из домена.

Чек-лист перед публикацией изменения

Чек-лист перед публикацией изменения — guía visual de DedicatedPHP
  • Есть ли у возможности стабильный идентификатор и однозначное бизнес-определение?
  • Указывает ли лимит единицу, область действия, период, конкурентный доступ и реакцию на превышение?
  • Применяется ли правило на сервере, в API и асинхронных процессах?
  • Проверяются ли по отдельности роли, возможности и контекст компании?
  • Есть ли у изменений тарифов и исключений срок действия, происхождение и аудит?
  • Существуют ли тесты для границы лимита, отзыва и изоляции нескольких компаний?

С этой моделью коммерческий каталог может развиваться, не превращая каждое изменение в поиск условных операторов. Платформа сохраняет понятные, измеримые и обоснованные правила как для продукта, так и для инженерии.

Хотите применить эти идеи в своем проекте?Давайте обсудим вашу PHP-платформу.
Посмотреть связанные услуги