关于 product-type-development
面向 Bagisto 开发者的产品类型开发指南,介绍如何注册自定义类型并扩展其行为。指南涵盖可售性、库存、定价、验证、管理界面和购物车处理。
主要功能
- 01配置并注册自定义产品类型
- 02通过 AbstractType 扩展产品行为
- 03设置可售性与库存规则
- 04定义定价和类型专属验证
- 05自定义管理界面和购物车数据
适用场景
- 01在 Bagisto 中实现订阅产品
- 02为服务类产品添加专属定价与验证
- 03调整自定义产品的库存和购物车逻辑
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ bagisto/ agent-skills --skill product-type-development安装后在 Claude Code 中输入/product-type-development确认已加载。
详细介绍
Bagisto 中的产品类型开发
概述
在 Bagisto 中创建自定义产品类型,可以定义符合业务需求的专用产品行为。无论您需要订阅产品、租赁商品、数字服务还是复杂的产品变体,自定义产品类型都能灵活满足您的商店需求。
适用场景
在以下情况下启用此技能:
- 在 Bagisto 中创建新的产品类型
- 构建订阅或服务类产品
- 实现自定义产品行为
- 添加特定类型的验证和定价
- 修改库存处理方式
@config:产品类型配置
基本配置结构
Config/product-types.php 文件是一个简单的 PHP 数组,用于注册您的产品类型:
<?php
return [
'subscription' => [
'key' => 'subscription',
'name' => 'Subscription',
'class' => 'Webkul\SubscriptionProduct\Type\Subscription',
'sort' => 5,
],
];
必需的配置属性
| 属性 | 描述 | 示例 |
|---|---|---|
key | 唯一标识符(与数组键一致) | 'subscription' |
name | 管理后台下拉菜单中显示的名称 | 'Subscription' |
class | 产品类型类的完整命名空间 | 'Webkul\SubscriptionProduct\Type\Subscription' |
sort | 下拉菜单中的排序位置(可选,默认为 0) | 5 |
Bagisto 如何使用此配置
1. 创建管理后台产品
- 从配置中读取所有已注册的产品类型
- 在“产品类型”下拉菜单中显示这些类型
- 使用
name显示名称,并使用sort排序
2. 实例化产品类型
- 使用
key查找产品的类型 - 创建
class的实例 - 调用该实例上的方法以处理产品行为
3. 加载配置
您的服务提供程序会合并配置:
public function register(): void
{
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/product-types.php',
'product_types'
);
}
多种产品类型
<?php
return [
'subscription' => [
'key' => 'subscription',
'name' => 'Subscription',
'class' => 'Webkul\SubscriptionProduct\Type\Subscription',
'sort' => 5,
],
'rental' => [
'key' => 'rental',
'name' => 'Rental Product',
'class' => 'Webkul\RentalProduct\Type\Rental',
'sort' => 6,
],
];
@abstract:AbstractType 方法
AbstractType 概述
Bagisto 中的每种产品类型都继承自 AbstractType 类:
<?php
namespace Webkul\Product\Type;
abstract class AbstractType
{
protected $product;
protected $isStockable = true;
protected $showQuantityBox = false;
protected $haveSufficientQuantity = true;
protected $canBeMovedFromWishlistToCart = true;
protected $additionalViews = [];
protected $skipAttributes = [];
}
要重写的关键方法
产品可售状态控制
isSaleable(): bool
控制产品是否显示为可购买:
public function isSaleable(): bool
{
if (! parent::isSaleable()) {
return false;
}
// Add custom availability logic
return true;
}
haveSufficientQuantity(int $qty): bool
检查是否有足够的可用数量:
public function haveSufficientQuantity(int $qty): bool
{
return true; // Custom logic based on subscription slots
}
库存控制
isStockable(): bool
确定产品是否使用库存跟踪:
public function isStockable(): bool
{
return false; // Subscriptions don't use traditional inventory
}
totalQuantity(): int
返回可用总数量:
public function totalQuantity(): int
{
return $this->product->subscription_slots ?? 0;
}
用户界面控制
showQuantityBox(): bool
控制是否显示数量输入框:
public function showQuantityBox(): bool
{
return true;
}
定价方法
getProductPrices(): array
返回结构化定价数据:
public function getProductPrices(): array
{
$basePrice = $this->product->price;
$discount = $this->product->subscription_discount ?? 0;
$finalPrice = $basePrice - ($basePrice * $discount / 100);
return [
'regular' => [
'price' => core()->convertPrice($basePrice),
'formatted_price' => core()->currency($basePrice),
],
'final' => [
'price' => core()->convertPrice($finalPrice),
'formatted_price' => core()->currency($finalPrice),
],
];
}
getPriceHtml(): string
生成用于显示的价格 HTML:
public function getPriceHtml(): string
{
return view('subscription::products.prices.subscription', [
'product' => $this->product,
'prices' => $this->getProductPrices(),
])->render();
}
验证方法
getTypeValidationRules(): array
返回产品类型专属字段的验证规则:
public function getTypeValidationRules(): array
{
return [
'subscription_frequency' => 'required|in:weekly,monthly,quarterly,yearly',
'subscription_discount' => 'nullable|numeric|min:0|max:100',
'subscription_duration' => 'nullable|integer|min:1',
'subscription_slots' => 'required|integer|min:1',
];
}
管理后台界面自定义
$additionalViews 属性
指定产品编辑页面中的其他 Blade 视图:
protected $additionalViews = [
'subscription::admin.catalog.products.edit.subscription-settings',
'subscription::admin.catalog.products.edit.subscription-pricing',
];
$skipAttributes 属性
指定要跳过的属性:
protected $skipAttributes = [
'weight',
'dimensions',
];
购物车集成
prepareForCart(array $data): array
在将产品添加到购物车之前处理产品数据:
public function prepareForCart(array $data): array
{
if (empty($data['subscription_frequency'])) {
return 'Please select subscription frequency.';
}
$cartData = parent::prepareForCart($data);
$cartData[0]['additional']['subscription_frequency'] = $data['subscription_frequency'];
$cartData[0]['additional']['subscription_start_date'] = $data['start_date'] ?? now()->addDays(1)->format('Y-m-d');
return $cartData;
}
@build:完整的订阅实现
软件包结构
packages/Webkul/SubscriptionProduct/
└── src/
├── Type/
│ └── Subscription.php
├── Config/
│ └── product-types.php
└── Providers/
└── SubscriptionServiceProvider.php
步骤 1:创建软件包结构
mkdir -p packages/Webkul/SubscriptionProduct/src/{Type,Config,Providers}
步骤 2:配置产品类型
文件: packages/Webkul/SubscriptionProduct/src/Config/product-types.php
<?php
return [
'subscription' => [
'key' => 'subscription',
'name' => 'Subscription',
'class' => 'Webkul\SubscriptionProduct\Type\Subscription',
'sort' => 5,
],
];
步骤 3:创建产品类型类
文件: packages/Webkul/SubscriptionProduct/src/Type/Subscription.php
<?php
namespace Webkul\SubscriptionProduct\Type;
use Webkul\Product\Helpers\Indexers\Price\Simple as SimpleIndexer;
use Webkul\Product\Type\AbstractType;
class Subscription extends AbstractType
{
public function getPriceIndexer()
{
return app(SimpleIndexer::class);
}
public function isStockable(): bool
{
return false;
}
public function showQuantityBox(): bool
{
return true;
}
public function isSaleable(): bool
{
if (! parent::isSaleable()) {
return false;
}
return true;
}
public function haveSufficientQuantity(int $qty): bool
{
return true;
}
public function totalQuantity(): int
{
return $this->product->subscription_slots ?? 0;
}
public function prepareForCart(array $data): array
{
if (empty($data['subscription_frequency'])) {
return 'Please select subscription frequency.';
}
$cartData = parent::prepareForCart($data);
$cartData[0]['additional']['subscription_frequency'] = $data['subscription_frequency'];
$cartData[0]['additional']['subscription_start_date'] = $data['start_date'] ?? now()->addDays(1)->format('Y-m-d');
return $cartData;
}
}
步骤 4:创建服务提供程序
文件: packages/Webkul/SubscriptionProduct/src/Providers/SubscriptionServiceProvider.php
<?php
namespace Webkul\SubscriptionProduct\Providers;
use Illuminate\Support\ServiceProvider;
class SubscriptionServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/product-types.php',
'product_types'
);
}
public function boot(): void
{
//
}
}
步骤 5:注册您的软件包
更新 composer.json
{
"autoload": {
"psr-4": {
"Webkul\\SubscriptionProduct\\": "packages/Webkul/SubscriptionProduct/src"
}
}
}
更新自动加载器
composer dump-autoload
注册服务提供程序
在 bootstrap/providers.php 中:
<?php
return [
App\Providers\AppServiceProvider::class,
// ... other providers ...
Webkul\SubscriptionProduct\Providers\SubscriptionServiceProvider::class,
];
清除缓存
php artisan optimize:clear
测试
php artisan tinker
# Test product type
>>> $product = \Webkul\Product\Models\Product::where('type', 'subscription')->first()
>>> $subscription = $product->getTypeInstance()
# Test methods
>>> $subscription->isStockable() // Should return false
>>> $subscription->showQuantityBox() // Should return true
>>> $subscription->isSaleable() // Should return true
# Test cart preparation
>>> $cartData = $subscription->prepareForCart(['quantity' => 2, 'subscription_frequency' => 'monthly'])
>>> $cartData[0]['additional'] // Should show subscription data
内置产品类型参考
| 类型 | 使用场景 | 主要功能 |
|---|---|---|
| 简单 | 基础产品 | 标准定价、库存跟踪 |
| 可配置 | 带有变体的产品 | 变体管理、基于属性的定价 |
| 虚拟 | 非实体产品 | 无需配送 |
| 分组 | 捆绑销售的相关产品 | 捆绑定价、组件选择 |
关键文件参考
| 文件 | 用途 |
|---|---|
Config/product-types.php | 产品类型注册 |
Type/ProductType.php | 产品类型类 |
Providers/ServiceProvider.php | 软件包注册 |
packages/Webkul/Product/src/Type/AbstractType.php | 基类 |
常见问题
- 忘记在服务提供程序中合并配置
$key与配置中的数组键不匹配- 未在
bootstrap/providers.php中注册服务提供程序 - 添加软件包后忘记运行
composer dump-autoload - 更改配置后未清除缓存
- 重写时忘记调用
parent::isSaleable() - 未在
prepareForCart()中正确处理购物车数据
评论
支持 Markdown