원클릭으로
extending-shopper
// Provides patterns for extending Shopper with custom sidebar items, component overrides, event listeners, and domain features like stock, pricing, and media. Use when customizing Shopper behavior.
// Provides patterns for extending Shopper with custom sidebar items, component overrides, event listeners, and domain features like stock, pricing, and media. Use when customizing Shopper behavior.
| name | extending-shopper |
| description | Provides patterns for extending Shopper with custom sidebar items, component overrides, event listeners, and domain features like stock, pricing, and media. Use when customizing Shopper behavior. |
// app/Sidebar/ShippingSidebar.php
namespace App\Sidebar;
use Shopper\Sidebar\AbstractAdminSidebar;
use Shopper\Sidebar\Contracts\Builder\Group;
use Shopper\Sidebar\Contracts\Builder\Item;
use Shopper\Sidebar\Contracts\Builder\Menu;
class ShippingSidebar extends AbstractAdminSidebar
{
public function extendWith(Menu $menu): Menu
{
$menu->group(__('shopper::layout.sidebar.catalog'), function (Group $group): void {
$group->weight(2); // Same weight as CatalogSidebar to merge
$group->item(__('Shipping'), function (Item $item): void {
$item->weight(5);
$item->useSpa();
$item->route('shopper.shipping.index');
$item->setIcon('untitledui-truck-01');
$item->setAuthorized($this->user->hasPermissionTo('browse_shipping'));
});
});
return $menu;
}
}
Register in AppServiceProvider:
use Shopper\Sidebar\SidebarBuilder;
public function boot(): void
{
$this->app['events']->listen(SidebarBuilder::class, ShippingSidebar::class);
}
$menu->group(__('Logistics'), function (Group $group): void {
$group->weight(5); // After CustomerSidebar (weight 4)
$group->setAuthorized();
$group->item(__('Shipping'), function (Item $item): void {
$item->weight(1);
$item->useSpa();
$item->route('shopper.shipping.index');
$item->setIcon('untitledui-truck-01');
});
});
| Group | Weight | Class |
|---|---|---|
| Dashboard | 1 | DashboardSidebar |
| Catalog | 2 | CatalogSidebar |
| Sales | 3 | SalesSidebar |
| Customers | 4 | CustomerSidebar |
$item->weight(int) - Position (lower = higher)$item->useSpa() - Enable wire:navigate$item->route('name') - Set route$item->setIcon('untitledui-*') - Icon$item->setAuthorized(bool) - Visibility conditionConfig files in config/shopper/components/:
// config/shopper/components/product.php
return [
'pages' => [
'product-index' => App\Livewire\Shopper\Products\Index::class,
'product-edit' => \Shopper\Livewire\Pages\Product\Edit::class,
],
'components' => [
'products.form.edit' => App\Livewire\Shopper\Products\EditForm::class,
],
];
Extend the base component:
namespace App\Livewire\Shopper\Products;
use Shopper\Livewire\Pages\Product\Index as BaseIndex;
class Index extends BaseIndex
{
public function table(Table $table): Table
{
return parent::table($table)
->columns([
...parent::table($table)->getColumns(),
TextColumn::make('custom_field'),
]);
}
}
Listen to Shopper events:
// EventServiceProvider
protected $listen = [
\Shopper\Core\Events\Products\ProductCreated::class => [YourListener::class],
\Shopper\Core\Events\Products\ProductUpdated::class => [],
\Shopper\Core\Events\Products\ProductDeleted::class => [],
\Shopper\Core\Events\Orders\OrderCreated::class => [SendOrderConfirmation::class],
\Shopper\Core\Events\Orders\OrderCompleted::class => [],
\Shopper\Core\Events\Orders\OrderPaid::class => [],
\Shopper\Core\Events\Orders\OrderCancel::class => [],
];
use Shopper\Core\Models\Inventory;
$product = Product::query()->find($id);
$inventory = Inventory::query()->where('is_default', true)->first();
$product->setStock(100, $inventory->id);
$product->decreaseStock($inventory->id, 5);
$currentStock = $product->getStock();
Amounts stored in cents, supports multi-currency:
use Shopper\Core\Models\Currency;
$product->prices()->create([
'currency_id' => Currency::where('code', 'USD')->first()->id,
'amount' => 2999, // $29.99
'compare_amount' => 3999, // $39.99 (crossed-out)
'cost_amount' => 1500, // $15.00 (cost)
]);
// Add thumbnail
$product->addMedia($file)
->toMediaCollection(config('shopper.media.storage.thumbnail_collection'));
// Add gallery images
$product->addMedia($file)
->toMediaCollection(config('shopper.media.storage.collection_name'));
// Get URL
$thumbnail = $product->getFirstMediaUrl(config('shopper.media.storage.thumbnail_collection'));
if (\Shopper\Feature::enabled('review')) {
// Show reviews
}
Configure in config/shopper/features.php.
| Function | Purpose |
|---|---|
shopper_table('products') | Prefixed table name (sh_products) |
shopper_setting('shop_name') | Get shop setting |
shopper_fallback_url() | Fallback image URL |
generate_number() | Order number with prefix |
shopper()->auth()->user() | Authenticated admin |
// config/shopper/routes.php
return [
'custom_file' => base_path('routes/shopper.php'),
];
// routes/shopper.php
use App\Livewire\Shopper\Shipping;
Route::get('shipping', Shipping::class)->name('shopper.shipping.index');
Provides coding standards and patterns for Shopper development. Use when creating or modifying Models, Actions, Enums, Livewire components, migrations, or tests in any Shopper package.
Provides patterns for building Livewire components in Shopper with Filament Forms, Tables, and Actions. Use when creating Pages, SlideOvers, or reusable components.