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

Support Laravel Package

vanilo/support

Vanilo Support provides the shared foundation for the Vanilo e-commerce suite: common contracts, helpers, traits, and base classes used across its components. A lightweight utility package for Laravel developers building modular online stores.

View on GitHub
Deep Wiki
Context7

Getting Started

vanilo/support is a low-level utility package and is almost never installed directly — it arrives transitively via vanilo/concord, vanilo/framework, or any concrete Vanilo module (products, cart, checkout, etc.). Install it explicitly only if you're building a standalone model or package that needs the shared contracts, traits, and helpers without pulling the full e-commerce stack:

composer require vanilo/support

Where to look first, in this order:

  1. src/Contracts/ — the interfaces your Eloquent models should implement (Sellable, Buyable, Priceable, Taxable, Shippable, Shoppable, etc.). These drive polymorphism across the whole Vanilo stack, so they are the most important surface.
  2. src/Traits/ — the batteries-included implementations: HasPrices, HasDimensions, HasName, HasSlug, HasMedia, HasImages, LoadsRelationships, Features.
  3. src/Enums/ — DimensionUnit, WeightUnit, and friends, used as typed enums for unit-safe comparisons.
  4. src/Features/ — the feature-flag machinery used to selectively enable/disable Vanilo subsystems.

First use case: you have an Eloquent model (say a SubscriptionPlan or a GiftCard) that needs to behave like something sellable inside Vanilo. Implement Sellable and use HasPrices, and your model can be put in a cart, have taxes computed, and be priced by the rest of the framework without custom glue.

Implementation Patterns

Contract-first models. The idiomatic pattern is: implement a Vanilo contract, pull in the matching trait. Don't implement the contract from scratch — the traits already handle the attributes, casts, and Money conversion in a way the other modules expect.

use Illuminate\Database\Eloquent\Model;
use Vanilo\Support\Contracts\Sellable;
use Vanilo\Support\Traits\HasPrices;

class GiftCard extends Model implements Sellable
{
    use HasPrices;
}

Extend, don't reinvent. Most day-to-day work happens by extending Vanilo's own models (Vanilo\Product\Models\Product, Vanilo\Cart\Models\Cart, etc.). Those already use the traits from this package, so inherited price accessors, dimensions, and slug handling all come for free. Your job is usually migrations and form validation, not reimplementing accessors.

Compose traits, don't stack them blindly. HasPrices + HasDimensions + HasSlug on the same model is common; each trait is scoped to a small set of columns, so there is little overlap. If you add your own price accessor and HasPrices, you will hit a trait-method collision — resolve with insteadof / as.

Feature flags for conditional behaviour. Wrap optional integrations (wishlist, reviews, payment gateways) with the Features trait + Featureable interface. Gate code paths with $model->isFeatureEnabled('...') rather than raw config() lookups, so toggling features config flips the whole stack consistently.

Money is typed, never float. HasPrices casts to a Money value object (through Concord's money resolver). Always operate on the accessor (e.g. $model->price) and use the value-object API; never read attributes['price'] directly, and never + two prices as numbers.

Unit-safe dimensions. HasDimensions pairs with DimensionUnit / WeightUnit enums. Convert units through the enum before arithmetic or persistance, so you don't silently mix cm and in in shipping calculations.

Gotchas and Tips

  • This is an internal package. The public API is stable within a Vanilo major version, but class names have moved between majors (e.g. Vanilo\Contracts\* → Vanilo\Support\Contracts\*). Pin vanilo/support to the same release line as the rest of your Vanilo packages and bump them together.
  • HasPrices expects specific column names — normally price, original_price, sale_price, all integer minor-units columns. If your migration uses cost or retail_price, the trait will return nulls rather than throwing, which is a silent bug. Mirror the naming.
  • Trait attribute vs. Eloquent accessor shadowing. If you define getPriceAttribute() yourself while HasPrices is in place, PHP trait precedence rules apply — you must use insteadof/as, or your accessor may be replaced. Check class_uses(YourModel::class) when in doubt.
  • Money resolver depends on Concord config. If Concord::money() returns null (missing/config typo in config/concord.php or config/vanilo.php), the price cast fails on hydrate, not on write — errors surface far from the cause. Verify the money driver is registered in a service provider during boot.
  • Features needs the Featureable interface. Using the trait alone compiles but the feature resolution methods type-hint the interface at some call sites; forgetting it throws a confusing TypeError at runtime, not at boot.
  • Feature config namespace is vanilo.features.*, not concord.features.* and not a per-package key. A common debugging trap is adding flags under the wrong root and wondering why nothing toggles.
  • LoadsRelationships reads a $model->load property (or config) and eagerly loads from it. If you add relations dynamically in code, remember to update that list too, or the trait won't see them.
  • Extension point: override contracts via Concord. Bind your own implementation of a Sellable/Priceable contract in a Concord module service provider (Concord::register(...)). This is the supported way to customise behaviour; extending the traits directly is supported but fragile across versions.
  • Debugging tip: when a price or dimension returns a string instead of a Money/Dimension object, check $model->getCasts() — the trait adds casts in its initialize* hook, so if your model's $casts overrides them by name, the trait's cast silently loses.
  • Don't reach for internal (@internal) helpers. They exist to support the surrounding modules and are the first thing to disappear between minor releases; stick to the documented contracts, traits, and enums.
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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core