Skip to content

Quick Start

This walkthrough takes you from zero to a working subscription in one sitting. We'll define features, build a plan, subscribe a user, gate access, track usage, and explore the lifecycle — each step with complete, copy-paste code.

If you haven't installed the package yet, do that first: Installation.

The Tashil facade

Most examples use the Tashil facade. The fully-qualified equivalent app('tashil') works everywhere too — use whichever your team prefers. Both resolve the same services.

Step 0 — Make your model Subscribable

A subscriber is any model that can hold a subscription. Add the contract and trait:

app/Models/User.php
use Foysal50x\Tashil\Contracts\Subscribable;
use Foysal50x\Tashil\Traits\HasSubscriptions;
use Illuminate\Foundation\Auth\User as Authenticatable;
 
class User extends Authenticatable implements Subscribable
{
    use HasSubscriptions;
}

Step 1 — Define your features

Features are defined once in a catalog, independent of any plan. Each has a type that decides how it behaves. We'll create one of each common kind:

use Foysal50x\Tashil\Facades\Tashil;
use Foysal50x\Tashil\Enums\ResetPeriod;
 
// A hard quota — enforced atomically.
$apiCalls = Tashil::feature('api-calls')->name('API Calls')->limit()->create();
 
// A simple on/off capability.
$darkMode = Tashil::feature('dark-mode')->name('Dark Mode')->boolean()->create();
 
// Tracked usage without a hard ceiling (e.g. storage in GB).
$storage  = Tashil::feature('storage-gb')->name('Storage (GB)')->consumable()->create();
 
// Charged per unit consumed against a balance your app controls.
$aiTokens = Tashil::feature('ai-tokens')->name('AI Tokens')->metered()->create();
 
// Reset the API quota every month.
$apiCalls->update(['reset_period' => ResetPeriod::Monthly]);

The five feature types are explained in detail on the Feature System page.

Step 2 — Build a plan

A package (plan) bundles pricing, billing cadence, an optional trial, and a set of features. The fluent builder reads top to bottom:

$pro = Tashil::package('pro')
    ->name('Pro Plan')
    ->price(29.99)
    ->monthly()
    ->trialDays(14)
    ->feature($apiCalls, value: '10000')   // 10,000 calls / month
    ->feature($darkMode, value: 'true')    // enabled
    ->feature($storage,  value: '50')      // 50 GB
    ->feature($aiTokens, value: '0.001')   // metered: $0.001 per token
    ->create();

The pivot value means different things per feature type: a numeric cap for limit, a string for boolean/enum, and — for metered — the unit price.

Step 3 — Subscribe a user

$user = User::find(1);
 
// With a 14-day trial (uses the plan's trial_days):
$subscription = Tashil::subscription()->subscribe($user, $pro, withTrial: true);

What status you get back depends on the plan and how you subscribed:

withTrialOnTrialaccess granted, billed at conversion
priced planPendingno access until the first invoice is paid
free planActiveaccess immediately

Why “Pending”?

By default, a paid plan does not grant access until money actually arrives. Subscribing issues an initial invoice; access begins when your app marks it paid. This closes the "free first period" gap. The full model lives in Billing Lifecycle.

Step 4 — Activate a paid subscription

Tashil never charges a card — your gateway integration does. When the charge succeeds, mark the invoice paid and Tashil takes it from there:

use Foysal50x\Tashil\Models\Invoice;
 
$invoice = Invoice::where('subscription_id', $subscription->id)->latest('id')->first();
 
// After your gateway confirms the charge:
$invoice->markAsPaid(); // → Tashil activates the subscription automatically
 
$subscription->refresh(); // status: Active, period anchored to the payment moment

Step 5 — Gate access and track usage

Now the day-to-day part. Check whether a user has a feature, then consume it:

// Boolean feature — is it on?
if ($user->hasFeature('dark-mode')) {
    // show the dark-mode toggle
}
 
// Limit feature — consume one unit. Returns false if it would exceed the cap.
if ($user->useFeature('api-calls')) {
    // within quota — do the work
} else {
    // over the limit — show an upgrade prompt
}
 
// Metered feature — charges units × unit_price via your balance.
// Returns false if the charge is declined (e.g. insufficient balance).
$user->useFeature('ai-tokens', 1500);
 
// Absolute reporting for storage-style values:
$user->reportStorage('storage-gb', 38.5); // the bucket is now 38.5 GB

The limit increment is a single atomic database operation — two concurrent requests can never both slip past the cap. See Feature System for the details.

Step 6 — Read the current state

$user->subscribed();                 // true if Active, OnTrial, or in grace
$user->onPlan('pro');                // on this specific plan?
$user->onTrial();                    // strictly on trial?
 
$user->featureValue('api-calls');    // '10000' (the snapshot value)
$user->featureUsage('api-calls');    // 1.0   (used so far)
$user->featureRemaining('api-calls');// 9999.0 (null means unlimited)

Step 7 — Lifecycle operations

// Grace cancel — keeps access until the period ends.
$user->cancelSubscription();
 
// Pause and resume — banks the remaining paid time.
$user->pauseSubscription();
$user->unpauseSubscription();
 
// Move plans. changePlan keeps the same row and prorates an upgrade:
$user->changePlan($enterprisePlan);
 
// Schedule a downgrade for the end of the current period:
$user->scheduleDowngrade($basicPlan);

Subscriptions covers each of these in depth, including the difference between changePlan() and switchPlan().

Step 8 — Gate routes and views

Three middleware and four Blade directives ship ready to use:

routes/web.php
Route::middleware('subscribed')->group(fn () => /* any valid subscription */);
Route::middleware('plan:pro')->group(fn () => /* the Pro plan only */);
Route::middleware('feature:api-calls')->group(fn () => /* needs this feature */);
resources/views/dashboard.blade.php
@feature('api-calls')
    <p>You have {{ $user->featureRemaining('api-calls') }} calls left this month.</p>
@else
    <p>Upgrade to unlock the API.</p>
@endfeature

Step 9 — See the analytics

$stats = Tashil::analytics()->dashboardSummary();
// MRR, active subscriptions, churn, trial conversion — all in one batched query.

Where to go next

You now have the whole flow working. Dive deeper into any concept:

Tashil — Subscription management for Laravel. Released under the MIT license.