miladtech/laravel-subscriptions 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

miladtech/laravel-subscriptions

Composer 安装命令:

composer require miladtech/laravel-subscriptions

包简介

Milad Tech Subscriptions is a flexible plans and subscription management system for Laravel, with the required tools to run your SAAS like services efficiently. It's simple architecture, accompanied by powerful underlying to afford solid platform for your business.

README 文档

README

MiladTech Subscriptions is a flexible plans and subscription management system for Laravel, with the required tools to run your SAAS like services efficiently. It's simple architecture, accompanied by powerful underlying to afford solid platform for your business.

Supports Laravel 11, 12 and 13 on PHP 8.2+, fully self-contained, with lifecycle events, grace periods, suspension, safe concurrent usage tracking, and a complete test suite.

Considerations

  • Payments are out of scope for this package. Listen to the lifecycle events (e.g. SubscriptionCanceled) to integrate your payment provider.
  • You may extend the core models when you need to override logic behind helper methods like renew(), cancel(), etc.

Installation

composer require miladtech/laravel-subscriptions

Migrations load automatically. Optionally publish resources:

php artisan vendor:publish --tag=miladtech-subscriptions-config
php artisan vendor:publish --tag=miladtech-subscriptions-migrations
php artisan migrate

Upgrading from v7? Read UPGRADE.md.

Usage

Add subscriptions to your model

Use the HasPlanSubscriptions trait on any subscriber model (usually User):

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use MiladTech\Subscriptions\Traits\HasPlanSubscriptions;

class User extends Authenticatable
{
    use HasPlanSubscriptions;
}

Create a plan with features

use MiladTech\Subscriptions\Models\Plan;

$plan = Plan::create([
    'name' => 'Pro',
    'description' => 'Pro plan',
    'price' => 9.99,
    'signup_fee' => 1.99,
    'currency' => 'USD',
    'invoice_period' => 1,
    'invoice_interval' => 'month', // hour|day|week|month|year
    'trial_period' => 15,
    'trial_interval' => 'day',
    'grace_period' => 3,
    'grace_interval' => 'day',
    'active_subscribers_limit' => 1000, // null = unlimited
]);

$plan->features()->saveMany([
    new PlanFeature(['name' => 'SMS', 'slug' => 'sms', 'value' => '100', 'resettable_period' => 1, 'resettable_interval' => 'month']),
    new PlanFeature(['name' => 'API Access', 'slug' => 'api-access', 'value' => 'true']),
    new PlanFeature(['name' => 'Legacy Import', 'slug' => 'legacy-import', 'value' => 'false']),
]);

Feature value semantics: "true" = enabled/unlimited · "false", "0", empty = disabled · numeric = countable limit · anything else = descriptive value (enabled).

Subscribe

$user->newPlanSubscription('main', $plan);            // starts now
$user->newPlanSubscription('main', $plan, $date);     // starts at a given date

Plans without a trial get trial_ends_at = null; with a trial, the paid period starts when the trial ends. Inactive plans and plans at their active_subscribers_limit throw (InactivePlanException, PlanSubscribersLimitReachedException). For admin/internal flows that attach private (inactive) plans manually, skip those checks:

$user->newPlanSubscription('main', $privatePlan, null, skipPlanChecks: true);

Check status

$subscription = $user->planSubscription('main');

$subscription->active();         // on trial, in period, or in grace — and not suspended
$subscription->onTrial();
$subscription->ended();
$subscription->onGracePeriod();  // ended but within the plan's grace window
$subscription->graceEndsAt();    // moment access is truly lost
$subscription->canceled();
$subscription->suspended();
$subscription->remainingDays();

$user->hasActivePlanSubscription();
$user->subscribedTo($planId);
$user->subscribedPlans();

Feature usage — safe by design

All writes run in a transaction with a row lock, so concurrent requests can never exceed a limit.

$subscription->canUseFeature('sms');          // one use
$subscription->canUseFeature('sms', 5);       // five uses at once

$subscription->recordFeatureUsage('sms');     // +1
$subscription->recordFeatureUsage('sms', 3);  // +3
$subscription->setFeatureUsage('sms', 10);    // absolute
$subscription->reduceFeatureUsage('sms', 2);

$subscription->getFeatureUsage('sms');        // used in the current window
$subscription->getFeatureRemainings('sms');   // PHP_INT_MAX for unlimited
$subscription->getFeatureValue('sms');        // raw value

recordFeatureUsage throws FeatureNotFoundException (unknown feature), FeatureUsageExceededException (limit reached) or SubscriptionException (inactive subscription) — catch them or gate with canUseFeature(). All package exceptions extend MiladTech\Subscriptions\Exceptions\SubscriptionException.

Resettable features (resettable_period/resettable_interval) reset automatically when their window elapses, aligned to the subscription start — even when several windows pass without activity.

Renew

$subscription->renew();    // one invoice period
$subscription->renew(3);   // three periods at once

Early renewal extends the current period from ends_at — subscribers never lose paid time — and keeps usage. Renewal after expiry starts a fresh period from now and clears usage. Renewing also reverts any scheduled cancellation.

Cancel / uncancel

$subscription->cancel();       // access remains until ends_at
$subscription->cancel(true);   // terminate immediately (ends trial too)
$subscription->uncancel();     // revert a scheduled cancellation

Suspend / resume

$subscription->suspend();        // e.g. failed payment — subscription becomes inactive
$subscription->resume();         // paused time is credited back to ends_at
$subscription->resume(false);    // resume without crediting paused time

Change plan

$subscription->changePlan($newPlan);

Usage is migrated to the new plan's features by slug: shared features keep their usage (limits may shrink or grow naturally), removed features lose their usage. Different billing frequency starts a new period today. Pass changePlan($newPlan, syncUsage: false) to wipe usage instead.

changePlan accepts inactive plans on purpose — changing an existing subscriber's plan is an internal/admin operation, and inactive plans are commonly private/custom plans attached manually. is_active only gates new public subscriptions.

Events

Every lifecycle change dispatches an event you can listen to:

SubscriptionCreated, SubscriptionRenewed, SubscriptionCanceled, SubscriptionUncanceled, SubscriptionSuspended, SubscriptionResumed, SubscriptionPlanChanged, SubscriptionExpired, SubscriptionTrialEnded, FeatureUsageRecorded, FeatureUsageReduced — all under MiladTech\Subscriptions\Events.

SubscriptionExpired and SubscriptionTrialEnded are fired (exactly once per subscription, grace-period aware) by the checker command. Schedule it in routes/console.php:

use Illuminate\Support\Facades\Schedule;

Schedule::command('subscriptions:check')->everyFifteenMinutes();

Scopes

PlanSubscription::ofSubscriber($user)->get();
PlanSubscription::findActive()->get();
PlanSubscription::findSuspended()->get();
PlanSubscription::findEndingTrial(3)->get();   // trials ending within 3 days
PlanSubscription::findEndedTrial()->get();
PlanSubscription::findEndingPeriod(3)->get();
PlanSubscription::findEndedPeriod()->get();

Models & config

Override table names or swap in your own models via the published config file (config/miladtech.subscriptions.php). Slugs are Persian-friendly (via pishran/laravel-persian-slug), and name/description are translatable (via spatie/laravel-translatable):

$plan = Plan::create(['name' => ['en' => 'Pro', 'fa' => 'حرفه‌ای'], ...]);

Subscription slugs are unique per subscriber (every user can own a subscription slugged main), and feature slugs are unique per plan (so plans can share feature slugs — that's what makes plan changes migrate usage).

Testing

composer test

CI runs the suite against every supported PHP/Laravel combination.

License

This software is released under The MIT License (MIT).

miladtech/laravel-subscriptions 适用场景与选型建议

miladtech/laravel-subscriptions 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 13 次下载、GitHub Stars 达 0, 最近一次更新时间为 2023 年 05 月 14 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「database」 「subscription」 「feature」 「laravel」 「value」 「plan」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 miladtech/laravel-subscriptions 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 miladtech/laravel-subscriptions 我们能提供哪些服务?
定制开发 / 二次开发

基于 miladtech/laravel-subscriptions 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 13
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 36
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2023-05-14