---
url: /blog/wrbnxat5/index.md
---
## ShopXO 插件钩子

根据源码分析,ShopXO 使用**自定义钩子系统**而非 ThinkPHP 原生的 `Event::listen`。

### 钩子工作原理

```mermaid
flowchart TD
    A[业务代码触发] --> B[MyEventTrigger]
    B --> C[ThinkPHP event函数]
    C --> D[已安装插件列表]
    D --> E[遍历插件 Hook.php]
    E --> F[Hook::handle 判断]
    F --> G{hook_name 匹配}
    G -->|匹配| H[执行插件逻辑]
    G -->|不匹配| I[跳过]
    H --> J[返回处理结果]
    I --> J
```

### 实际使用位置

**插件钩子统一入口**: `app/plugins/{插件名}/Hook.php`

### 具体使用示例

**1. 分销插件监听商品保存** ([app/plugins/distribution/Hook.php:63-293](vscode-webview://125e1dv2hcu76dnlb0sp660otp8n50f7eped0m6hr14o0jsuivdk/app/plugins/distribution/Hook.php#L63-L293)):

```php
class Hook
{
    public function handle($params = [])
    {
        if(!empty($params['hook_name']))
        {
            // 获取插件配置
            $base = BaseService::BaseConfig();
            $this->plugins_config = $base['data'];
            
            // 通过 switch 匹配不同的钩子名称
            switch ($params['hook_name'])
            {
                // 商品规格扩展处理
                case 'plugins_service_goods_spec_extends_handle':
                    $ret = $this->GoodsSpecExtendsHandle($params);
                    break;
                    
                // 订单提交后处理
                case 'plugins_service_buy_order_insert_end':
                    $ret = $this->BuyOrderInsertHandle($params);
                    break;
                    
                // 商品列表数据处理
                case 'plugins_service_goods_list_handle_end':
                    $this->GoodsHandleEnd($params);
                    break;
            }
        }
    }
    
    // 具体处理方法
    private function GoodsSpecExtendsHandle($params)
    {
        // 处理分销等级规格
        // ...
    }
}
```

### 监听 `plugins_service_goods_save_end` 的示例

如果您想监听商品保存钩子,需要在插件的 `Hook.php` 中添加:

```php
// app/plugins/your_plugin/Hook.php
class Hook
{
    public function handle($params = [])
    {
        if(!empty($params['hook_name']))
        {
            switch ($params['hook_name'])
            {
                // 监听商品保存后钩子
                case 'plugins_service_goods_save_end':
                    $this->GoodsSaveEnd($params);
                    break;
            }
        }
    }
    
    /**
     * 商品保存后处理
     */
    private function GoodsSaveEnd($params)
    {
        $goods_id = $params['goods_id'];
        $goods_data = $params['data'];
        
        // 自定义逻辑,例如:
        // 1. 同步到ERP系统
        // 2. 发送通知
        // 3. 更新搜索引擎
        
        return DataReturn('处理成功', 0);
    }
}
```

### 钩子注册机制

ShopXO 的钩子是**自动注册**的:

1. 插件安装后会在 `sxo_plugins` 表中注册
2. 系统通过 `PluginsAdminService` 扫描已安装插件
3. 每个 `Hook.php` 的 `handle()` 方法会接收到所有钩子触发
4. 通过 `switch($params['hook_name'])` 匹配并处理需要的钩子

### 常用钩子列表

| 钩子名称                               | 触发时机       | 使用场景           |
| -------------------------------------- | -------------- | ------------------ |
| `plugins_service_goods_save_end`       | 商品保存后     | 数据同步、日志记录 |
| `plugins_service_order_insert_end`     | 订单创建后     | 分销计算、库存扣减 |
| `plugins_view_assign_data`             | 视图赋值前     | 数据注入、变量修改 |
| `plugins_service_buy_order_insert_end` | 购买订单插入后 | 佣金计算、优惠处理 |
