The Bagisto Proxy Pattern is one of the framework’s most powerful extension mechanisms.
It lets developers override core models without editing vendor files or forking the platform.
You might add a method to the Product model, modify a relationship, or replace an entire model with a custom implementation.
In most frameworks that means editing vendor files (wiped on the next update) or forking the platform (which you then maintain forever).
Bagisto Dev Doc solves this with the Proxy Pattern.
It adds a thin layer of indirection that lets any package replace a core model at runtime.
No changes to the core code are required.
- Think of a restaurant that never hardcodes the chef on its menu. Instead, it simply says “prepared by the chef on duty.”
- Swap the person behind the pass, and every dish is now cooked by the new chef. There is no need to reprint the menu.
- Bagisto’s proxies work the same way. The code always asks for ProductProxy, and whoever is registered at that moment does the cooking.
Bagisto Proxy Pattern: Before vs. After
1: Without the Proxy Pattern
- Adding one method to
Productmeans editing core – lost on the nextcomposer update. - However, relationships often hardcode Product::class
- Overriding a model means grep-and-replacing dozens of references.
2: With Bagisto’s Proxy Pattern
- Extend the model in your own package; register it in one line.
- Relationships reference
ProductProxy::modelClass(), resolved to whatever is registered. - Every reference across the codebase updates automatically – nothing to grep.
How the Bagisto Proxy Pattern Works
Bagisto sits on Konekt Concord, a Laravel modularization library.
Every model is paired with two small companions: a Contract and a Proxy.
The Contract defines the model’s interface, while the Proxy resolves that contract to the concrete model currently registered.
Application code references the proxy, never the concrete class.
Bagisto Proxy Pattern Under the Hood
1. Bagisto Proxy Pattern: The Model, the Contract, and the Proxy
The contract is just an empty interface that gives the model a stable, abstract name:
|
1 2 3 4 |
<?php // packages/Webkul/Product/src/Contracts/Product.php namespace Webkul\Product\Contracts; interface Product {} |
The proxy has no body at all – all the intelligence lives in the parent ModelProxy:
|
1 2 3 4 5 |
<?php // packages/Webkul/Product/src/Models/ProductProxy.php namespace Webkul\Product\Models; use Konekt\Concord\Proxies\ModelProxy; class ProductProxy extends ModelProxy {} |
2. Registering the Model with Concord
Each package’s ModuleServiceProvider lists the models it owns in a single array:
|
1 2 3 4 5 6 7 8 9 10 11 |
<?php // packages/Webkul/Product/src/Providers/ModuleServiceProvider.php class ModuleServiceProvider extends CoreModuleServiceProvider { protected $models = [ Product::class, ProductImage::class, ProductInventory::class, // ...more ]; } |
On boot, Concord derives each model’s contract and binds the pair in the container:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php // vendor/konekt/concord/src/BaseServiceProvider.php protected function registerModels() { foreach ($this->models as $key => $model) { $contract = is_string($key) ? $key : $this->convention->contractForModel($model); $this->concord->registerModel( $contract, $model, config('concord.register_route_models', true) ); } } |
3. Referencing the Proxy
Relationships never name a concrete class – they call ::modelClass() on the proxy:
|
1 2 3 4 5 6 7 8 9 |
<?php // packages/Webkul/Product/src/Models/Product.php public function categories(): BelongsToMany { return $this->belongsToMany( CategoryProxy::modelClass(), 'product_categories' ); } |
The convention runs both directions – a wishlist points back at a product the same way:
4. How modelClass() Resolves the Real Class
|
1 2 3 4 5 6 7 8 9 10 11 |
<?php // vendor/konekt/concord/src/Proxies/ModelProxy.php public static function modelClass() { return static::getInstance()->targetClass(); } protected function targetClass(): string { return $this->concord->model($this->contract); } |
|
1 2 3 4 5 6 |
<?php // vendor/konekt/concord/src/Concord.php public function model(string $abstract) { return Arr::get($this->models, $abstract); } |
5. Forwarding static calls
You can also call model methods directly on the proxy.
The __callStatic method forwards each call to the real model class.
|
1 2 3 4 5 6 7 8 9 |
<?php // vendor/konekt/concord/src/Proxies/BaseProxy.php public static function __callStatic($method, $parameters) { return call_user_func( static::getInstance()->targetClass() . '::' . $method, ...$parameters ); } |
Bagisto Proxy Pattern: Overriding a Core Model
1. Extend the core model
|
1 2 3 4 5 6 7 8 9 10 11 |
<?php // packages/YourVendor/Catalog/src/Models/Product.php namespace YourVendor\Catalog\Models; use Webkul\Product\Models\Product as BaseProduct; class Product extends BaseProduct { public function isEligibleForFreeShipping(): bool { return$this->price >= 100; } } |
2. Register it against the contract
|
1 2 3 4 5 |
<?php // packages/Webkul/Marketplace/src/Providers/MarketplaceManager.php $this->app->concord->registerModel(ProductContract::class, Product::class); $this->app->concord->registerModel(CartItemContract::class, CartItem::class); |
|
1 2 3 4 5 6 7 8 9 10 11 |
<?php // vendor/konekt/concord/src/Concord.php public function registerModel(string $abstract, string $concrete, $registerRouteModel = true) { if (!is_subclass_of($concrete, $abstract, true)) { thrownewInvalidArgumentException("Class {$concrete} must extend or implement {$abstract}."); } $this->models[$abstract] = $concrete; $this->app->alias($concrete, $abstract); // ...re-registers route models and resets the cached proxy } |
Final Thoughts : Why the Bagisto Proxy Pattern Matters
By pairing every model with a contract and a proxy, Bagisto makes model substitution simple.
What is usually a fork-or-suffer problem becomes a one-line registration.
Your customizations stay outside the core, making upgrades much easier.
You can also hire Laravel developers to build custom solutions on Laravel. To explore available extensions, check out the Bagisto Extension marketplace.