roundly-consulting/money-for-laravel
Money for Laravel brings precise monetary handling to Laravel apps with an immutable Money value object, Eloquent casts, and Blade formatting helpers. Parse, calculate, and format currency amounts without floating-point errors, keeping prices, totals, and invoices clean and testable.
composer require <vendor>/<package> and publish the config: php artisan vendor:publish --provider="<Vendor>\<Package>\<Package>ServiceProvider" --tag=config. The published config file is the first place to look — it holds the model map that everything else (repositories, factories, relations) resolves through.php artisan config:show <package> to confirm the resolved values before writing any code.// config/<package>.php
' models' => [
'post' => App\Models\Post::class,
],
// tests/Feature/PostTest.php
$post = PostFactory::new()->create();
$this->assertInstanceOf(App\Models\Post::class, $post);
Config-driven model swapping. The intended workflow is to never hard-code the package's models. Override the config entry (or the container binding, if the provider binds an interface) in a service provider or in tests/TestCase::setUp() so every consumer — factories, relations, policies — picks up the host's model.
protected function setUp(): void
{
parent::setUp();
config()->set('<package>.models.post', App\Models\Post::class);
}
Factories as the primary test seam. Use the package factories rather than Model::create() so the model swap is exercised the same way production code exercises it. Layer states and relationships on top:
PostFactory::new()
->for($user)
->state(['published_at' => now()])
->hasComments(3)
->create();
Bind interfaces, resolve models. If the package exposes a contract, bind your implementation in a service provider and let the package resolve through the container; if it only exposes a config map, treat the config as the single source of truth and read it via config() rather than a cached property so runtime swaps (tenant, test, feature flag) take effect.
Multi-tenant / host-scoped use. Where a "host" swaps the model per request or per tenant, set the config in middleware before the package resolves anything, and reset it in a terminating callback or test teardown — otherwise the swap leaks into the next resolution in long-running workers (Octane, queues).
assertInstanceOf and relation type hints failed silently or with confusing Class not found / type errors. Pin ^1.0.3 and re-run factory-based tests after upgrading — failures you had papered over with withoutEvents() or manual setModel() calls may now resolve correctly, or reveal an incorrect config entry.php artisan config:cache must be re-run. A stale cache looks exactly like the pre-1.0.3 factory bug: the old class keeps getting instantiated.Factory::new() has been constructed (or after a relation is loaded) has no effect on the already-built instance — set it first, then build.finally blocks or middleware termination, otherwise a worker picks up the previous tenant's model on the next job.get_class($model) from the factory result and compare it with config('<package>.models.<key>'). A mismatch means either a stale config cache or a package/provider version older than 1.0.3.How can I help you explore Laravel packages today?