PHP code example of err0r / larasub

1. Go to this page and download the library: Download err0r/larasub library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

err0r / larasub example snippets




namespace App\Models;

use Err0r\Larasub\Traits\HasSubscription;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasSubscription;
    
    // Your existing model code...
}



use Err0r\Larasub\Builders\FeatureBuilder;

// Consumable feature (trackable usage)
$apiCalls = FeatureBuilder::create('api-calls')
    ->name(['en' => 'API Calls', 'ar' => 'مكالمات API'])
    ->description(['en' => 'Number of API calls allowed'])
    ->consumable()
    ->sortOrder(1)
    ->build();

// Non-consumable feature (boolean access)
$prioritySupport = FeatureBuilder::create('priority-support')
    ->name(['en' => 'Priority Support'])
    ->description(['en' => 'Access to priority customer support'])
    ->nonConsumable()
    ->sortOrder(2)
    ->build();



use Err0r\Larasub\Builders\PlanBuilder;
use Err0r\Larasub\Enums\Period;
use Err0r\Larasub\Enums\FeatureValue;

// Create initial plan version
$premiumPlan = PlanBuilder::create('premium')
    ->name(['en' => 'Premium Plan', 'ar' => 'خطة مميزة'])
    ->description(['en' => 'Access to premium features'])
    ->sortOrder(2)
    ->versionLabel('1.0.0')
    ->price(99.99, 'USD')
    ->resetPeriod(1, Period::MONTH)
    ->published()
    ->addFeature('api-calls', fn ($feature) => $feature
        ->value(1000)
        ->resetPeriod(1, Period::DAY)
        ->displayValue(['en' => '1000 API Calls'])
        ->sortOrder(1)
    )
    ->addFeature('priority-support', fn ($feature) => $feature
        ->value(FeatureValue::UNLIMITED)
        ->displayValue(['en' => 'Priority Support Included'])
        ->sortOrder(2)
    )
    ->build();



// Get plan (automatically uses latest published version)
$plan = Plan::slug('premium')->first();

// Subscribe user
$subscription = $user->subscribe($plan);

// Subscribe with custom dates
$subscription = $user->subscribe($plan, 
    startAt: now(), 
    endAt: now()->addYear()
);

// Create pending subscription (useful for payment processing)
$subscription = $user->subscribe($plan, pending: true);



// Check feature access
if ($user->hasFeature('priority-support')) {
    // User has access to priority support
}

// Check consumable feature usage
if ($user->canUseFeature('api-calls', 5)) {
    // User can make 5 API calls
    $user->useFeature('api-calls', 5);
}

// Get remaining usage
$remaining = $user->remainingFeatureUsage('api-calls');

// Accessing plan properties directly
$price = $subscription->plan->price;
$features = $subscription->plan->features;

// Access through plan version
$price = $subscription->planVersion->price;
$features = $subscription->planVersion->features;



// Basic subscription
$subscription = $user->subscribe($plan);

// Advanced options
$subscription = $user->subscribe($plan, 
    startAt: now()->addWeek(),     // Future start
    endAt: now()->addYear(),       // Custom end date
    pending: false                 // Active immediately
);

// Pending subscription (for payment processing)
$pendingSubscription = $user->subscribe($plan, pending: true);



$subscription = $user->subscriptions()->first();

// Status checks
$subscription->isActive();     // Currently active
$subscription->isPending();    // Awaiting activation
$subscription->isCancelled();  // Marked for cancellation
$subscription->isExpired();    // Past end date
$subscription->isFuture();     // Scheduled to start

// Status transitions (useful for event handling)
$subscription->wasJustActivated();
$subscription->wasJustCancelled();
$subscription->wasJustResumed();
$subscription->wasJustRenewed();



// Cancel subscription
$subscription->cancel();                    // Cancel at period end
$subscription->cancel(immediately: true);   // Cancel immediately

// Resume cancelled subscription
$subscription->resume();
$subscription->resume(startAt: now(), endAt: now()->addMonth());

// Renew subscription
$newSubscription = $subscription->renew();              // From end date
$newSubscription = $subscription->renew(startAt: now()); // From specific date



// By status
$user->subscriptions()->active()->get();
$user->subscriptions()->pending()->get();
$user->subscriptions()->cancelled()->get();
$user->subscriptions()->expired()->get();

// By plan
$user->subscriptions()->wherePlan($plan)->get();
$user->subscriptions()->wherePlan('premium')->get(); // Using slug

// By renewal status
$user->subscriptions()->renewed()->get();     // Previously renewed
$user->subscriptions()->notRenewed()->get();  // Not yet renewed
$user->subscriptions()->dueForRenewal()->get(); // Due in 7 days
$user->subscriptions()->dueForRenewal(30)->get(); // Due in 30 days



// Basic feature check
$user->hasFeature('priority-support');        // Has the feature
$user->hasActiveFeature('priority-support');  // Has active subscription with feature

// Consumable feature checks
$user->canUseFeature('api-calls', 10);        // Can use 10 units
$user->remainingFeatureUsage('api-calls');    // Remaining usage count

// Next available usage (for reset periods)
$nextReset = $user->nextAvailableFeatureUsage('api-calls');
// Returns Carbon instance, null (unlimited), or false (no reset)



// Record usage
$user->useFeature('api-calls', 5);

// Get usage statistics
$totalUsage = $user->featureUsage('api-calls');
$usageBySubscription = $user->featuresUsage(); // All features

// Through specific subscription
$subscription->useFeature('api-calls', 3);
$subscription->featureUsage('api-calls');
$subscription->remainingFeatureUsage('api-calls');



// Get plan feature details
$planFeature = $subscription->planFeature('api-calls');
echo $planFeature->value;              // Usage limit
echo $planFeature->reset_period;       // Reset frequency
echo $planFeature->reset_period_type;  // Reset period type
echo $planFeature->display_value;      // Human-readable value
echo $planFeature->is_hidden;          // Whether feature is hidden from users



// Creating hidden features
$plan = PlanBuilder::create('premium')
    ->addFeature('api-calls', fn ($feature) => $feature
        ->value(1000)
        ->displayValue('1,000 API calls')
        // Feature is visible to users by default
    )
    ->addFeature('internal-tracking', fn ($feature) => $feature
        ->value('enabled')
        ->displayValue('Internal tracking')
        ->hidden()  // Hide this feature from user interfaces
    )
    ->addFeature('admin-feature', fn ($feature) => $feature
        ->value('enabled')
        ->hidden(true)  // Explicitly hide
    )
    ->addFeature('visible-feature', fn ($feature) => $feature
        ->value('enabled')
        ->visible()  // Explicitly make visible (default behavior)
    )
    ->build();

// Query visible/hidden features
$visibleFeatures = $planVersion->visibleFeatures;  // Only visible features
$allFeatures = $planVersion->features;             // All features (visible + hidden)

// Using scopes
$visible = PlanFeature::visible()->get();          // All visible plan features
$hidden = PlanFeature::hidden()->get();            // All hidden plan features

// Check visibility
$feature = $planVersion->features->first();
$feature->isVisible();  // true/false
$feature->isHidden();   // true/false



use Err0r\Larasub\Models\Feature;

// Get a feature instance
$feature = Feature::slug('api-calls')->first();

// All plan-feature pivot rows for this feature
$planFeatures = $feature->planFeatures;

// All plan versions that 



// Create new version of existing plan
$newVersion = PlanBuilder::create('premium') // Same slug
    ->versionLabel('2.0.0')           // Display label
    ->price(129.99, 'USD')            // Updated price
    ->resetPeriod(1, Period::MONTH)
    ->published()
    ->addFeature('api-calls', fn ($feature) => $feature
        ->value(2000)                 // Increased limit
        ->resetPeriod(1, Period::DAY)
    )
    ->build();

// Specify exact version number
$specificVersion = PlanBuilder::create('premium')
    ->versionNumber(5)                // Explicit version
    ->versionLabel('5.0.0-beta')
    ->price(199.99, 'USD')
    ->build();



$plan = Plan::slug('premium')->first();

// Get versions
$versions = $plan->versions;                    // All versions
$currentVersion = $plan->currentVersion();      // Latest published & active
$latestVersion = $plan->versions()->latest()->first(); // Latest by number

// Version properties
$version = $plan->versions->first();
$version->version_number;           // e.g., 2
$version->version_label;            // e.g., "2.0.0"
$version->getDisplayVersion();      // Returns label or "v{number}"
$version->isPublished();
$version->isActive();
$version->isFree();

// Version operations
$version->publish();
$version->unpublish();



// Subscribe to specific version (optional)
$user->subscribe($plan);           // Uses current published version
$user->subscribe($planVersion);    // Uses specific version

// Access version data
$subscription->planVersion->price;           // Version-specific price
$subscription->planVersion->features;        // Version-specific features
$subscription->planVersion->version_number;  // 2
$subscription->planVersion->getDisplayVersion(); // "2.0.0" or "v2"



use Err0r\Larasub\Events\SubscriptionEnded;
use Err0r\Larasub\Events\SubscriptionEndingSoon;

// Triggered when subscription expires
SubscriptionEnded::class

// Triggered when subscription is ending soon (configurable, default: 7 days)
SubscriptionEndingSoon::class



namespace App\Listeners;

use Err0r\Larasub\Events\SubscriptionEnded;
use Illuminate\Contracts\Queue\ShouldQueue;

class HandleEndedSubscription implements ShouldQueue
{
    public function handle(SubscriptionEnded $event): void
    {
        $subscription = $event->subscription;
        $user = $subscription->subscriber;
        
        // Send notification, downgrade access, etc.
        $user->notify(new SubscriptionExpiredNotification($subscription));
    }
}



use Err0r\Larasub\Resources\{
    FeatureResource,
    PlanResource,
    PlanVersionResource,
    PlanFeatureResource,
    SubscriptionResource,
    SubscriptionFeatureUsageResource
};

// Transform feature
return FeatureResource::make($feature);

// Transform plan with versions
return PlanResource::make($plan);

// Transform plan version with features
return PlanVersionResource::make($planVersion);

// Transform subscription with plan version
return SubscriptionResource::make($subscription);

// Transform feature usage
return SubscriptionFeatureUsageResource::make($usage);



return [
    // Database table names
    'tables' => [
        'plans' => 'plans',
        'plan_versions' => 'plan_versions',
        'features' => 'features',
        'subscriptions' => 'subscriptions',
        // ...
    ],
    
    // Event scheduling
    'schedule' => [
        'check_ending_subscriptions' => '* * * * *', // Every minute
    ],
    
    // Notification settings
    'subscription_ending_soon_days' => 7,
    
    // Model configurations
    'models' => [
        'plan' => \Err0r\Larasub\Models\Plan::class,
        'subscription' => \Err0r\Larasub\Models\Subscription::class,
        // ...
    ],
];
bash
php artisan vendor:publish --tag="larasub-config"
bash
# Publish all migrations
php artisan vendor:publish --tag="larasub-migrations"
php artisan migrate
bash
php artisan vendor:publish --tag="larasub-config"
bash
# Check for ending subscriptions (usually run via scheduler)
php artisan larasub:check-ending-subscriptions
bash
# Seed sample data for development
php artisan larasub:seed