Download the PHP package vnuswilliams/laravel-subscription without Composer

On this page you can find all versions of the php package vnuswilliams/laravel-subscription. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package laravel-subscription

Laravel Subscription

Latest Version on Packagist Total Downloads PHP Laravel

A robust, fluent, and fully payment-agnostic Laravel package for managing subscription plans, lifecycle states (trial, grace period, cancellation), and consumable feature quotas.

This package does not handle any payments. It exclusively manages subscription business logic: who has access to what, for how long, and how much they have left. You plug in the payment provider of your choice (Stripe, Paystack, Flutterwave, PayPal…) around it.

This documentation is always release in french version.


Table of Contents

  1. Architecture
  2. Installation
  3. Configuring Plans in the Database
  4. Preparing the Subscriber Model
  5. Entry Points: Three Ways to Use the Package
  6. Managing Subscriptions
  7. Features & Quotas
  8. Lifecycle & Grace Period
  9. Route Protection Middleware
  10. Laravel Events
  11. Artisan Command
  12. Full Recipe: Application Service
  13. API Reference
  14. Tips & Best Practices

Architecture

The package is built on a strict separation of concerns:

Golden rule: the HasSubscriptions trait contains no business logic. It delegates everything to the SubscriptionManager. This keeps the logic testable, injectable, and independent of the Eloquent model.


Installation

1. Install via Composer

The ServiceProvider and Facade are auto-discovered by Laravel. No manual registration needed.

2. Publish the configuration and migrations

Use the package install command to publish both the configuration file and the migrations in one step:

If config/subscriptions.php or any package migration already exists in your application, subscription:install deletes the existing file first and regenerates a fresh copy from the package. By default, the subscriptions.subscriber_key_type config value is id, which creates the classic integer subscriber_id column. Set it to uuid or ulid before running the package migrations when the model using HasSubscriptions has a UUID/ULID primary key. The migrations also use subscriptions.price.precision and subscriptions.price.scale for plan and subscription prices, defaulting to a decimal(12, 2) column so values like 100 and 19.99 are both supported.

3. (Optional) Generate the application service

The package provides a generator command that scaffolds a ready-to-use SubscriptionService tailored to the model that carries the HasSubscriptions trait in your application.

Run it and pass your model name via the --model option:

Omit the option to be prompted interactively:

This generates app/Services/SubscriptionService.php pre-filled with your model. If the file already exists, the command asks for confirmation before overwriting it. See the Full Recipe section for the generated content and usage examples.

Tip: the model name is case-insensitive — user, User, and USER all produce User in the generated file.


Configuring Plans in the Database

The package does not create your plans automatically. You insert them via a seeder, a migration, or your application's admin interface.

Here is the expected structure for a monthly plan with features:

Tip: centralise all your feature slugs in a FeatureEnum in your application. This prevents typos and gives you IDE autocompletion.


Preparing the Subscriber Model

Add the HasSubscriptions trait to any Eloquent model that needs to subscribe to a plan: User, Company, Team, Organization…

That's it. The trait automatically exposes the subscription() relationship and all of the package's fluent methods directly on your model.


Entry Points: Three Ways to Use the Package

The package exposes three interfaces depending on your context. Choose the one that fits your situation.

1. Via the Trait (on the model)

The most fluent syntax for one-off calls directly on the Eloquent instance:

Ideal in Observers, Policies, or quick checks inside a Controller.

2. Via the Facade (anywhere in the app)

The Laravel-style static syntax, accessible everywhere without injection:

Ideal in Controllers, Actions, Jobs, or Listeners.

3. Via SubscriptionManager injection (in your services)

The recommended approach for complex business logic. Fully testable, with no static dependency:

Tip: in a dedicated subscription service, always prefer direct injection. The Facade is handy for isolated calls, but makes unit testing harder.


Managing Subscriptions

Subscribing to a plan

Pass the plan slug (string) or a Plan instance directly:

The created subscription stores its own price. If you do not pass a custom price, it copies the plan price at subscription time. You can override it for negotiated prices, add-ons, discounts, or prorated amounts:

If the plan has trial_days > 0, the status will automatically be set to on_trial and trial_ends_at will be calculated. No additional action required.

Subscribing with a custom expiration

Useful for free plans or fixed-duration promotional offers:

Switching plans (upgrade / downgrade)

Cancelling a subscription

Cancellation does not cut access immediately. The user retains access until ends_at, then the grace period activates if configured. This is the expected behaviour for an end-of-period cancellation.

To check whether a subscription is cancelled but still running:

Revoking access immediately

To cut access without waiting for the end of the period (suspension for non-payment, terms of service violation, etc.):

Renewing a subscription

Starts a full new cycle from now. Useful after a successful payment:

Checking subscription status


Features & Quotas

Boolean features (yes/no access)

A boolean feature is simply attached to a plan or not. If it is not in the plan's feature list, access is denied.

For a boolean feature, the $amount parameter is ignored. canConsume('feature', 0) and canConsume('feature', 1) return the same result.

Consumable features (quotas)

The standard flow for a quota feature: check → act → consume.

Important: always call canConsume() before consume(). The package does not throw an exception if you consume beyond the quota — that guard is your responsibility.

Releasing a slot (decrementing consumption)

When you delete a resource, release the corresponding slot:

release() decrements used safely (never below 0). This is more reliable than deleting the last consumption record.

Inspecting quotas (for dashboards)

Example usage in a Blade view for a progress bar:


Lifecycle & Grace Period

The full lifecycle of a subscription:

The hasAccess() method is your single source of truth. It returns true for the active, on_trial, on_grace_period, and canceled (if ends_at is in the future) states. It returns false for expired and suppressed subscriptions.

Configuring the grace period per plan

The grace period is configured in the plan data (grace_days column). No global configuration is required. Each plan can have its own duration:


Route Protection Middleware

The package automatically registers the subscribed middleware. Use it in your route files:

When access is denied, the middleware returns:

To customise this behaviour, extend CheckSubscription and rebind it in your AppServiceProvider.


Laravel Events

The package dispatches native Laravel events on every lifecycle transition. Register your listeners in EventServiceProvider or using Laravel 11+ #[AsEventListener] attributes.

Event Triggered when Typical use case
SubscriptionCreated A new subscription is created Welcome email, access activation
SubscriptionCanceled Subscription cancelled (end of period) Retention email, exit survey
SubscriptionEnteredGracePeriod Expiration reached, grace activated Urgent payment reminder email
SubscriptionExpired Grace period over, access cut Suspension, notification, archiving
FeatureQuotaReached A feature quota is exhausted Upsell notification, admin alert

Artisan Command

The subscription:check-lifecycle command iterates over all subscriptions in the database and performs any missing status transitions (active → on_grace_period → expired).

It is useful for users who do not log in often: their subscription will move to grace or expire even without an incoming request, and the relevant events will be dispatched correctly.

Schedule it to run daily in routes/console.php (Laravel 11+):

Or in app/Console/Kernel.php (Laravel 10 and earlier):


Full Recipe: Application Service

Generate a ready-to-use SubscriptionService by running the generator command with the model that carries the HasSubscriptions trait:

This creates app/Services/SubscriptionService.php pre-wired to your model. Here is what it contains and how to use it:

Usage in a Controller:


API Reference

HasSubscriptions Trait

Method Return Description
subscription() MorphOne Eloquent relationship to the latest subscription
subscribeTo($plan, $expiration, $immediately, $price) Subscription Subscribes or switches if an active subscription exists
switchTo($plan, $immediately, $price) Subscription Switches plan
renewSubscription() Subscription Renews from now
hasActiveSubscription() bool Is the subscription valid? (active, trial, grace)
currentPlan() Plan\|null Current plan
subscriptionExpiresAt() Carbon\|null Expiration date
canConsume($slug, $amount) bool Quota or boolean access available?
consume($slug, $amount) SubscriptionUsage Consumes $amount units
release($slug, $amount) SubscriptionUsage Releases $amount units
balance($slug) int Remaining balance (PHP_INT_MAX if unlimited)
totalCharges($slug) int Total allocated by the plan
usedCharges($slug) int Amount consumed

Subscription Model

Method Return Description
isActive() bool Status is active AND ends_at is in the future
isOnTrial() bool trial_ends_at is in the future
isOnGracePeriod() bool Within the grace window
isCanceled() bool Cancelled (access may still be available)
isSuppressed() bool Immediately revoked
isExpired() bool No access remaining
hasAccess() bool Global source of truth
cancel() static End-of-period cancellation
suppress() static Immediate access revocation
renew() static Renewal from now

Available Enums


Tips & Best Practices

Centralise your feature slugs in an enum. A typo like 'max-employes' instead of 'max-employees' silently returns false. FeatureEnum::MAX_EMPLOYEES->value never makes that mistake.

Always check before consuming. The package does not throw an exception if you call consume() when the quota is exhausted. The canConsume() guard is your responsibility.

Use release() when deleting resources. If a user deletes an employee, release the slot. Otherwise the counter stays inflated and the user loses capacity they should get back.

Do not confuse cancel() and suppress(). cancel() is a normal cancellation — access is maintained until the end of the paid period. suppress() is an administrative or punitive suspension — access is cut immediately.

Inject SubscriptionManager in your services, use the Facade in your controllers. Services need to be unit-testable — avoid the Facade in classes you test with pest or phpunit. In a Controller or a Livewire component, the Facade is perfectly appropriate.

Handle exceptions. The package throws typed exceptions for error cases:

Schedule the subscription:check-lifecycle command without fail. Without it, an inactive user who makes no requests will never see their subscription transition to expired in the database — and SubscriptionExpired events will never be dispatched.


License

This package is open-sourced software licensed under the MIT license.


All versions of laravel-subscription with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
illuminate/contracts Version ^10.0|^11.0|^12.0|^13.0
illuminate/database Version ^10.0|^11.0|^12.0|^13.0
illuminate/events Version ^10.0|^11.0|^12.0|^13.0
illuminate/http Version ^10.0|^11.0|^12.0|^13.0
illuminate/routing Version ^10.0|^11.0|^12.0|^13.0
illuminate/support Version ^10.0|^11.0|^12.0|^13.0
illuminate/console Version ^10.0|^11.0|^12.0|^13.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package vnuswilliams/laravel-subscription contains the following files

Loading the files please wait ...