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

Shops For Laravel Laravel Package

roundly-consulting/shops-for-laravel

Shops for Laravel adds lightweight shop and storefront support to Laravel apps, with simple configuration and an Eloquent-friendly API for managing shops and related data.

View on GitHub
Deep Wiki
Context7

Getting Started

This release (1.1.0) is about model resolution: the package now gives you a single, canonical way to ask "which Shop class is actually in play?" instead of assuming it's the packaged Shop.

Minimal steps:

  1. Install and publish config as usual, then open the published config file first — that's where the model swap lives.
  2. Decide whether you need a custom model. If the packaged Shop is enough, you can stop: ShopModel::shop() returns Shop and the packaged ShopFactory builds Shop.
  3. If you need extra columns, relations, or behaviour, create App\Models\Shop extends Vendor\Package\Models\Shop, point the config at it, and run your migrations.
  4. Use ShopModel::shop() anywhere you'd otherwise hardcode Shop::class — relations, seeders, policies, form requests, test factories.

First use case — a fresh install with a tenant-specific relation:

use Vendor\Package\Support\ShopModel;

Schema::create('products', function (Blueprint $table) {
    $table->foreignIdFor(ShopModel::shop())->constrained();
});

The guarantee you get from 1.1.0: ShopModel::shop() returns your subclass only if it extends Shop. If the configured class is unrelated, missing, or misconfigured, you silently get Shop back rather than a fatal error. That's a deliberate fallback, not a validation failure — treat it as such.

Implementation Patterns

Swap the model, then resolve it — never both.

// config/shop.php  (verify the exact key in your published config)
'model' => App\Models\Shop::class,
// App\Models\Shop
class Shop extends Vendor\Package\Models\Shop
{
    public function owner(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }
}

Resolve at the call site, not at class-load time. Model resolution belongs inside methods and closures so it survives config changes and test overrides:

// Good
public function shops()
{
    return $this->hasMany(ShopModel::shop());
}

// Bad — evaluated once, frozen forever
protected $shopClass = ShopModel::shop();

Seeders and factories. The packaged ShopFactory now builds whatever the config points at, so Shop::factory() and ShopModel::shop()::factory() produce the same class. Prefer the latter in package-agnostic code:

ShopModel::shop()::factory()->count(3)->create();

If your subclass has required columns, define states on your own factory and extend the packaged one:

class ShopFactory extends Vendor\Package\Database\Factories\ShopFactory
{
    public function definition(): array
    {
        return [...parent::definition(), 'plan' => 'basic'];
    }
}

Remember to wire it up via newFactory() on your model, or the packaged factory will still be used.

Testing the swap. Because the fallback is silent, add a test that asserts resolution rather than assuming it:

public function test_configured_shop_model_is_used(): void
{
    config()->set('shop.model', App\Models\Shop::class);

    $this->assertSame(App\Models\Shop::class, ShopModel::shop());
}

Integration tip — policies and validation. Anything keyed by model class name (Gate::policy, Rule::exists, morphMap) must use the resolved class too, otherwise you get rules validated against the base table while your subclass writes elsewhere.

Gotchas and Tips

  • The silent fallback is the main pitfall. A typo in the config key, a class that doesn't extend Shop, or a swapped-in model that fails to autoload all degrade to Shop without complaint. The only reliable signal is the helper's return value — assert it in a test and log it once at boot in non-production.
  • Extending is mandatory, not optional. ShopModel::shop() checks is_subclass_of(..., Shop::class). A model that re-implements the behaviour from scratch but extends Model directly gets ignored. Also note the check is against Shop itself, not the packaged base class via an interface — subclass chains are fine, sibling implementations are not.
  • Relationship declarations are evaluated lazily, so hasMany(ShopModel::shop()) is safe — but only if the method is called after config is loaded. Config cached via config:cache is still fine; a config()->set() in a service provider that runs after the model is first resolved is not.
  • The factory fix is the part most likely to bite on upgrade. If you'd worked around the old behaviour by overriding factories or hardcoding Shop::class in seeders, remove those workarounds — you'll now get double-application or class mismatches.
  • Upgrade checklist for 1.1.0: grep for hardcoded Shop::class and Shop::factory(), replace with ShopModel::shop(), then run your suite. There are no breaking changes here, but any code that relied on the factory always returning the packaged model will behave differently now.
  • Debugging tip: when behaviour looks like "wrong model", dump ShopModel::shop() and get_class() on a fetched instance side by side. Mismatches almost always trace back to the config key or a missing extends.
  • Extension point to watch: ShopModel::shop() is the seam the package has committed to. Route your own resolution through it rather than reading config directly — that way the package can change how the class is determined without breaking you, and you only ever have one source of truth.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib