Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Dashed Ecommerce Core Laravel Package

dashed/dashed-ecommerce-core

Dashed Ecommerce Core is a Laravel/PHP foundation for building online stores, offering core commerce models, cart and checkout logic, and extensible services for products, orders, payments, and catalog management.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish in one pass, then read the service provider before you write a single line of application code.

composer require dashed/dashed-ecommerce-core
php artisan vendor:publish --provider="Dashed\Ecommerce\EcommerceServiceProvider"
php artisan migrate

Read these four things in this order — they tell you 90% of what the package does:

  1. The service provider (src/*ServiceProvider.php). Every bind()/singleton() is a seam you can swap. Note the config keys it merges and the migrations it loads — that's your override surface.
  2. The published config (config/dashed-ecommerce.php or similar). Look for arrays of model class-strings (product, variant, order, cart) and money/currency settings. Model-swapping via config is the standard convention for this category of package; if it's there, it's the primary extension mechanism.
  3. database/migrations/. Read the foreign keys — they dictate the order in which you can safely seed data and which tables you may extend.
  4. src/Contracts/. If contracts exist, the container bindings in the provider are your swap points. If they don't, you'll be extending concrete models instead, which changes your upgrade strategy.

First use case to validate the install: create a product with at least one variant and a price, resolve the cart service from the container, add the variant, and place an order. Do this in a tinker session or a throwaway test before touching real application code — it exercises the money handling, the variant/pricing resolution, and the order lifecycle in one shot, and any of those three failing is a signal to stop and read further.

$product = Product::create([...]);
$variant = $product->variants()->create([...]);
$cart = app(Cart::class); // or whatever the contract resolves to
$cart->add($variant, 1);
$order = $cart->toOrder();

If that sequence is awkward — if you find yourself reaching for DB::table() or manually setting foreign keys — the package's own conventions are probably different from what you assumed, and it's worth rereading the provider before building on top of it.

Implementation Patterns

Configure, don't fork. For a package with this little downstream usage, your biggest risk is patching vendor code that you then can't update. Push every customization through config, container bindings, and events. If a requirement genuinely can't be met that way, write an adapter class in your own namespace that wraps the package and inject that — it gives you a single file to rewrite if you ever have to replace the dependency.

Model swapping is usually the intended integration path. E-commerce cores typically let you point config at your own subclasses so you can add relations, scopes, and accessors without touching vendor/. The pattern:

// config/dashed-ecommerce.php
'models' => [
    'product' => App\Models\Product::class,
    'order'   => App\Models\Order::class,
],

// app/Models/Product.php
class Product extends \Dashed\Ecommerce\Models\Product
{
    public function scopeActive($q) { return $q->where('is_active', true); }
}

Do this before your first migration run. Swapping models after data exists means your polymorphic relations (if any) and any hard-coded class names in the package's own seeders/factories will be inconsistent. If the package uses morph maps, register your subclasses there too.

Treat money as integers, end to end. Most cores in this space store minor units and expose a Money value object or a cast. Never do float arithmetic across the boundary — cast to integer at the edge, do all math in integers, format only at render time. If the package ships a formatting helper, use it rather than number_format, or you'll get currency-symbol and decimal-place drift between the admin and the storefront.

Wire side effects through events, not model observers on vendor classes. Order placement, payment capture, refunds, and stock changes should each fire an event. Register listeners for email, inventory decrement, and analytics. Observers on vendor models work but break silently on package upgrades; event listeners are the contract the package author actually intended. Check whether events fire inside a database transaction — if they do, use DB::afterCommit() or ShouldHandleEventsAfterCommit on listeners that touch external services.

Cart vs. order is a service boundary. Carts are mutable and session/identity-scoped; orders are immutable snapshots. The most common integration bug in this architecture is pricing the order from live product prices instead of copying the line-item price at checkout time. Verify that toOrder() snapshots prices, tax rates, and currency onto the order lines. If it doesn't, add that in your order-creation wrapper — it's non-negotiable for accounting.

Resolve services from the container, never new. Anything with a contract should be app(Contract::class) or constructor-injected. This is what makes the package testable and swappable, and it's how your own tests should consume it.

Test against the package's factories. Use RefreshDatabase and the shipped factories to build realistic fixtures; hand-rolling inserts will drift from the schema on every migration. Write one integration test per lifecycle transition (cart → order, order → paid, order → refunded) so package upgrades fail loudly in CI rather than in production.

Gotchas and Tips

  • Pin the exact version. Zero dependents, a single release in 2026, and a small maintainer surface means breaking changes may land without a major bump. Use "dashed/dashed-ecommerce-core": "1.2.3" (exact) rather than ^1.2, and upgrade deliberately with the integration tests above as your gate.
  • vendor:publish is destructive on re-publish. If you publish the config and later upgrade, Laravel will overwrite it or leave it stale depending on whether you pass --force. Keep published config under version control and diff it against the vendor copy after every upgrade. Migrations are worse: once published, they're yours, and the package's subsequent migration changes won't reach you. Prefer not publishing migrations unless you must modify them, and if you do, note the original filename in a comment so you can spot divergence.
  • Migration ordering bites on shared databases. The package's tables almost certainly have FK dependencies between product/variant/order/line-item. If you're adding columns via your own migrations, timestamp them after the package's — and if the package loads migrations from vendor/, your migration timestamps must still sort later. A php artisan migrate:fresh --seed on a clean DB is the only reliable check.
  • Money rounding on tax and discounts. Rounding per line vs. rounding the order total produces different numbers, and the package picks one. Find out which, and make sure your invoice renderer and your accounting export agree with it. This shows up as one-cent discrepancies that are miserable to trace.
  • Watch for N+1 on variants and prices. Listing a catalog page typically triggers variant → price → currency lookups per row. Eager-load explicitly (with(['variants.prices'])) on every index query; the package usually won't do it for you, and the default $with on the models is often empty by design.
  • Debugging toolkit: php artisan about to confirm the provider registered, php artisan vendor:publish --list to see available tags, app()->bound(SomeContract::class) in tinker to confirm bindings, and DB::listen() in a local middleware to see exactly which queries a cart operation emits. When behavior surprises you, the resolved class is usually not the one you assumed — get_class(app(Cart::class)) settles it in one line.
  • Extension points, ranked by safety: events and listeners → contracts and container bindings → config model swaps → subclassing concrete models → editing vendor files (never). If you find yourself at level four or five, add an adapter layer and file an upstream issue.
  • Budget for ownership. With no dependents, you are effectively the first serious integrator. Expect to read source rather than docs, and keep a short internal NOTES.md of every seam you've used — it turns a future package swap from an archaeology project into an afternoon.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect