nafiswatsiq/subbase
Advanced subscription management for Laravel with a Filament admin panel. Build plans with multi-currency pricing and features, manage full subscription lifecycles, add promo codes and discounts, plus optional Spatie roles and custom models. Built on laravelcm/laravel-subscriptions.
Advanced subscription management system for Laravel with Filament admin panel integration. Built on top of laravelcm/laravel-subscriptions with multi-currency support, optional role/permission support, and custom model flexibility.
spatie/laravel-permission when installed, but still works without itcomposer require nafiswatsiq/subbase
php artisan subbase:install
php artisan migrate
When updating to a newer version, use the upgrade command instead of subbase:install:
composer require nafiswatsiq/subbase:^x.x
# Publish only new migrations (safe, never overwrites existing)
php artisan subbase:upgrade --migrations
# Force overwrite config and views to latest version
php artisan subbase:upgrade --force
# Selectively upgrade specific assets
php artisan subbase:upgrade --config # config only
php artisan subbase:upgrade --views # views only
# Run new migrations
php artisan migrate
Note:
php artisan subbase:installandvendor:publishskip files that already exist. Usesubbase:upgrade --forceto overwrite them with the latest version.
In your User model just use trait like this:
namespace App\Models;
use Laravelcm\Subscriptions\Traits\HasPlanSubscriptions;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use HasPlanSubscriptions;
}
In your app/Providers/Filament/AdminPanelProvider.php:
use Nafiswatsiq\Subbase\SubbasePlugin;
class AdminPanelProvider extends PanelProvider
{
public function panel(Panel $panel): Panel
{
return $panel
->plugin(SubbasePlugin::make())
// ... rest of configuration
}
}
The service provider is auto-discovered via composer.json extra field. If auto-discovery is disabled, add manually in bootstrap/providers.php:
Nafiswatsiq\Subbase\SubbaseServiceProvider::class,
Publish config file:
php artisan vendor:publish --tag="subbase-config"
Edit config/subbase.php to customize:
If your app installs spatie/laravel-permission, you can control access to the plugin with permission names in config/subbase.php:
'permissions' => [
'plan' => 'manage subbase plans',
'subscription' => 'manage subbase subscriptions',
'feature' => 'manage subbase features',
],
Behavior:
spatie/laravel-permission is installed, Filament resource access follows those permission strings.ViewAny:Plan and ViewAny:Subscription for the built-in resources.Override default models in config/subbase.php:
'models' => [
'plan' => App\Models\CustomPlan::class,
'feature' => App\Models\CustomFeature::class,
'subscription' => App\Models\CustomSubscription::class,
'subscription_usage' => App\Models\CustomSubscriptionUsage::class,
]
Ensure your custom models extend the base models from nafiswatsiq/subbase.
Subbase uses laravelcm/laravel-subscriptions under the hood to handle all core subscription logic (subscribing, canceling, checking features, swapping plans, etc.).
For complete documentation on how to use the underlying subscription methods on your User model, please refer to the official repository: 👉 laravelcm/laravel-subscriptions on GitHub
Subbase adds several powerful features on top of the base package:
Plans in Subbase can store prices for multiple currencies natively. Use the built-in Filament panel to set prices for USD, EUR, IDR, etc. The pricing component will automatically display the correct currency based on your subbase.php locale mappings.
Usage Examples:
use Nafiswatsiq\Subbase\Models\Plan;
$plan = Plan::first();
// Retrieve price for a specific currency
$priceInUSD = $plan->getPriceForCurrency('USD');
// Retrieve price automatically based on application locale (e.g., 'en-US' mapped to 'USD')
// Returns the base price if the currency is not set
$priceForLocale = $plan->getPriceForLocale(app()->getLocale());
// Check if a plan has a price set for a specific currency
if ($plan->hasCurrencyPrice('EUR')) {
// ...
}
// Get all currencies configured for the plan
$currencies = $plan->getAvailableCurrencies(); // ['USD', 'IDR', 'EUR']
// Programmatically set a price for a currency
$plan->setPriceForCurrency('EUR', 15.99)->save();
Subbase includes a comprehensive discount engine for creating promo codes, seasonal offers, and pricing discounts. Supports percentage-based and fixed-amount discounts with full validation, usage limits, and plan/feature targeting.
Admin Panel — A full Filament resource is available at /admin/discounts to manage discounts.
Usage Examples:
use Nafiswatsiq\Subbase\Models\Discount;
// Find a discount by code
$discount = Discount::findByCode('NEWYEAR50');
// Check if a discount is currently valid (active, within date range, under usage limit)
if ($discount->isValid()) {
// Calculate discounted price
$discountedAmount = $discount->calculateDiscount(100.00); // $50.00 (50% off)
}
// Check if discount applies to a specific plan
$applies = $discount->appliesToPlan($plan->getKey());
// Check if discount applies to a specific feature
$applies = $discount->appliesToFeature($feature->getKey());
// Get a human-readable value (e.g., "50%" or "USD 50.00")
echo $discount->getFormattedValue();
// Increment usage counter after successful application
$discount->markUsed();
| Type | Description | Example |
|---|---|---|
percentage |
Percentage off the total amount | 10% = $10 off $100 |
fixed |
Fixed amount off | 50.00 = $50 off any amount |
| Field | Description |
|---|---|
name |
Internal name for the discount |
code |
Unique promo code used during checkout |
type |
percentage or fixed |
value |
The discount amount/percentage value |
currency |
Optional currency restriction (e.g., USD, IDR) |
min_amount |
Minimum order amount required |
max_uses |
Maximum number of times the code can be used |
is_active |
Enable/disable the discount |
starts_at |
Schedule the discount to start at a specific date |
expires_at |
Set an expiry date for the discount |
applies_to |
Restrict to plans, features, or both |
applicable_plans |
Array of specific plan IDs the discount applies to |
applicable_features |
Array of specific feature IDs the discount applies to |
The PlanPriceHelper integrates with the discount engine to resolve pricing with active discounts:
use Nafiswatsiq\Subbase\Helpers\PlanPriceHelper;
// Resolve price with the best matching discount (highest priority)
$result = PlanPriceHelper::resolveWithDiscounts($plan, 'USD');
// Returns: ['original' => 99.00, 'discounted' => 49.50, 'hasDiscount' => true, ...]
// Format prices with discount info for display
$formatted = PlanPriceHelper::formatWithDiscounts($plan, 'USD');
// Returns: ['formatted_original' => '$99.00', 'formatted_discounted' => '$49.50', ...]
The built-in plan-list component automatically detects active discounts and displays:
No additional configuration is needed — discounts are automatically resolved and displayed when viewing the pricing table.
The discount feature adds the following tables:
discounts — Main discounts tablediscount_plan — Pivot table linking discounts to plansdiscount_subscription — Tracks which discounts were applied to which subscriptionsRun the migration:
php artisan migrate
You can mark specific plans as "Featured" (your most popular plan).
To easily retrieve only the featured plans in your application, you can use the featured attribute:
use Nafiswatsiq\Subbase\Models\Plan;
$plan = Plan::active()->first();
$plan->featured;
Subbase includes a modern, reusable Blade component built with Tailwind CSS to display pricing plans on your frontend.
To use the pricing table in any of your Blade views, simply include the component:
<!-- You can also provide a custom route name for the subscribe button -->
<x-subbase::plan-list subscribe-route="your.custom.checkout.route" />
// Example Route
Route::get('subscribe/{plan}', function ($plan) {
dd($plan);
})->name('your.custom.checkout.route');
sort_order.subscribe-route prop to direct users to your custom checkout flow.If you need to customize the look and feel of the pricing table, you can publish the view file to your application. This will copy the Blade file to resources/views/vendor/subbase/components/plan-list.blade.php.
Run the following command:
php artisan vendor:publish --tag="subbase-views"
Translations are organized in resources/lang/{locale}/subbase/:
plan.php - Plan-related labelssubscription.php - Subscription-related labelsdiscount.php - Discount-related labelsOverride by publishing translations:
php artisan vendor:publish --tag="subbase-translations"
The MIT License (MIT). Please see License File for more information.
How can I help you explore Laravel packages today?