realrashid/plan-craft
Plan Craft is a Laravel package for defining and managing subscription plans, features, and usage limits. Attach plans to any model, gate features by plan, and track subscriptions through a clean, flexible API—ideal for SaaS apps that need simple, code-driven plan and feature management.
v2.0.0 is a platform-jump release: it targets Laravel 13, PHP 8.3+, and ships test tooling on Testbench v11 / Pest v4. Treat it as a fresh install rather than an in-place bump if you are coming from a 1.x line.
Minimal steps:
php -v # must be >= 8.3
composer why-not laravel/framework 13.*
composer require <vendor>/<package>:^2.0
php artisan vendor:publish --provider="<Vendor>\\<Package>\\<Package>ServiceProvider"
vendor/bin/pest
Where to look first:
composer.json — the require / require-dev blocks are the contract. orchestra/testbench: ^11.0 and pestphp/pest: ^4.0 are the load-bearing entries.tests/ — with Pest v4 the suite doubles as the integration documentation for Testbench v11 bootstrapping.phpunit.xml / phpunit.xml.dist — Pest 4 reads through PHPUnit, and Testbench v11 changed the default bootstrap wiring.First use case: stand the package up inside a fresh Laravel 13 skeleton, not your existing app. This isolates package-vs-framework problems from your application's own upgrade debt.
Pin the platform, not just the package. Because v2 hard-requires PHP 8.3, set an explicit platform in composer.json so CI and local agree:
"config": { "platform": { "php": "8.3.0" } }
Testbench v11 for extension work. If you are building on top of the package (custom drivers, decorators, macros), copy the package's own Testbench setup rather than inventing one — v11's TestCase bootstrapping differs from v10 and the package authors have already solved it. A typical extension test:
use Orchestra\Testbench\TestCase;
class CustomDriverTest extends TestCase
{
protected function getPackageProviders($app): array
{
return [\Vendor\Package\PackageServiceProvider::class];
}
protected function defineEnvironment($app): void
{
$app['config']->set('package.driver', 'custom');
}
}
Pest v4 idioms. New tests should use it() / test() with datasets and expect() chains; the v4 expectation API is stricter about types, so legacy ->toBe() on loosely-typed values may now fail where it previously passed. Convert opportunistically rather than in one sweep.
CI matrix. Minimum viable matrix for a v2 consumer:
php: ['8.3', '8.4']
laravel: ['13.*']
Adding Laravel 12 rows is pointless — this release does not claim it.
Service container over facades where you can. Laravel 13 leans further into constructor injection and deferred providers; resolving the package's contracts through the container keeps you insulated from provider-registration changes in future majors.
orchestra/testbench: ^10 in a transitive dev dependency will silently drag you back. Run composer why orchestra/testbench if the suite fails with bootstrap errors.pestphp/pest-plugin-laravel) must be on their v4-compatible lines; version skew shows up as missing expectations rather than clear errors. Check every pest-plugin-* entry in require-dev.php artisan about reveals the resolved framework version and provider list; php -r "echo PHP_VERSION;" vs composer show php catches platform-config mismatches.bindings / singletons, published config, and any Macroable traits are the stable surface. If you are hooking into internals to make v2 work, that's a signal to file an upstream issue before upgrading your whole app.composer.lock and vendor/ when moving between majors — stale locks are the single most common cause of "it says Laravel 13 but behaves like 11."How can I help you explore Laravel packages today?