docs: 追加经验#19 — AdminSidebarInit items vs item 属性名陷阱 + 检查清单更新
parent
44553442e0
commit
6c18dd38f4
|
|
@ -342,6 +342,73 @@ class Index
|
|||
|
||||
---
|
||||
|
||||
### 19. AdminSidebarInit 子菜单:`items`(复数)不是 `item`(单数)
|
||||
|
||||
**症状**:sidebar 显示"VR票务"顶级菜单,但子菜单项(场馆配置/座位模板/电子票等)全部丢失,控制台无报错。
|
||||
|
||||
**根因**:`Hook.php` 的 `AdminSidebarInit` 里,子菜单数组的 key 写成 `item`:
|
||||
|
||||
```php
|
||||
// ❌ 错误:ShopXO 渲染器不认识 `item`
|
||||
$params[] = [
|
||||
'id' => 'plugins-vr_ticket',
|
||||
'name' => 'VR票务',
|
||||
'item' => [ // ← 单数,ShopXO sidebar 不认
|
||||
['name' => '场馆配置', 'url' => ..., 'is_show' => 1],
|
||||
['name' => '座位模板', 'url' => ..., 'is_show' => 1],
|
||||
]
|
||||
];
|
||||
```
|
||||
|
||||
ShopXO 后台 sidebar 模板(`app/admin/view/default/public/menu.html`)渲染逻辑:
|
||||
|
||||
```html
|
||||
{{foreach $left_menu as $v}}
|
||||
{{if empty($v['items'])}} <!-- 无子菜单,渲染为顶级单项 -->
|
||||
{{else /}} <!-- 有子菜单,渲染为可折叠父项 -->
|
||||
<ul class="admin-sidebar-sub">
|
||||
{{foreach $v.items as $vs}} ... {{/foreach}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
{{/foreach}}
|
||||
```
|
||||
|
||||
ShopXO 渲染器检查的是 **`items`(复数)**,不是 `item`(单数)。`item` 被当作普通属性忽略,所有子菜单项静默丢失。
|
||||
|
||||
**修复**:
|
||||
|
||||
```php
|
||||
// ✅ 正确:`items` 复数
|
||||
$params[] = [
|
||||
'id' => 'plugins-vr_ticket',
|
||||
'name' => 'VR票务',
|
||||
'items' => [ // ← 复数,ShopXO sidebar 渲染器认识
|
||||
['name' => '场馆配置', 'url' => ..., 'is_show' => 1],
|
||||
['name' => '座位模板', 'url' => ..., 'is_show' => 1],
|
||||
]
|
||||
];
|
||||
```
|
||||
|
||||
**调试方法**:在浏览器控制台执行:
|
||||
|
||||
```javascript
|
||||
// 提取 sidebar 中所有菜单项 URL
|
||||
const items = document.querySelectorAll('a.menu-item');
|
||||
const vr = [];
|
||||
items.forEach(a => {
|
||||
const t = a.textContent.trim();
|
||||
if(t.includes('VR')||t.includes('票务')||t.includes('场馆')||t.includes('座位'))
|
||||
vr.push(a.href + ' => ' + t);
|
||||
});
|
||||
console.log(vr.join('\n'));
|
||||
```
|
||||
|
||||
对比 `Hook.php` 中注册的所有 URL,即可发现哪些子菜单项未出现在 DOM 中。
|
||||
|
||||
**教训**:ShopXO 大量使用复数形式约定(`items`、`menus`、`params`),遇到"数据明明传了但不渲染"的问题时,优先检查属性名的单复数是否与渲染器约定一致。
|
||||
|
||||
---
|
||||
|
||||
## 📌 开发前检查清单
|
||||
|
||||
接手本插件时,逐项确认以下内容:
|
||||
|
|
@ -351,6 +418,7 @@ class Index
|
|||
- [ ] 引用 JS/CSS 前先查 ShopXO 是否已自带(`public/static/common/lib/`),优先本地文件而非 CDN
|
||||
- [ ] 插件模板使用 `$public_host` 时,控制器已显式传递(不依赖框架自动赋值)
|
||||
- [ ] Hook.php 返回数组包含 `id`、`url`、`name`、`is_show`
|
||||
- [ ] Hook.php `AdminSidebarInit` 子菜单数组的 key 是 `items`(复数),不是 `item`(单数)
|
||||
- [ ] Admin.php 有缓存锁机制保护 `initialize()` 免于每次请求检查表
|
||||
- [ ] 改字段名之前查过 Service 层源码或实际表结构
|
||||
- [ ] 插件视图路径使用 `../../../plugins/vr_ticket/view/...` 前缀
|
||||
|
|
|
|||
Loading…
Reference in New Issue