推荐位 alias 会修改甚至为 null,而业务代码又依赖 alias 做硬编码查找,这导致数据与代码之间的绑定关系出现混乱,维护成本和出错风险上升
1、– `official-website-management-system`.recommendation_slots definition
CREATE TABLE `recommendation_slots` ( `id` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL, `alias` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `name` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT '', `cover_image_id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '封面图', `more_redirect_url` varchar(300) COLLATE utf8mb4_unicode_ci DEFAULT '', `title` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT '', `keywords` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT '', `description` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT '', `content` text COLLATE utf8mb4_unicode_ci, `usage` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '用法', `status` tinyint unsigned DEFAULT '1' COMMENT '是否显示 1可用 2不可用 4删除', `created_at` datetime DEFAULT NULL, `updated_at` datetime DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx-alias` (`alias`), KEY `idx-status` (`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- `official-website-management-system`.recommendation_contents definition CREATE TABLE `recommendation_contents` ( `id` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL, `slot_id` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `type` tinyint unsigned DEFAULT '5' COMMENT '类型 1文章 2视频 3音频 4图片 5链接 6小程序 7应用 9其他', `title` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT '', `cover_image_id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '封面图', `image_1_id` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `image_2_id` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `image_3_id` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `text_1` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '文本一', `text_2` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '文本二', `text_3` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '文本三', `link_1` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '链接一', `link_2` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '链接二', `link_3` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '链接三', `keywords` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT '', `description` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT '', `content` text COLLATE utf8mb4_unicode_ci, `click_count` int unsigned DEFAULT '0', `status` tinyint unsigned DEFAULT '1' COMMENT '是否显示 1显示 2不显示', `order_number` int unsigned DEFAULT '1' COMMENT '排序,数值越大越靠前', `created_at` datetime DEFAULT NULL, `updated_at` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx-slot_id` (`slot_id`), KEY `idx-status` (`status`), KEY `idx-order_number` (`order_number`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
现有推荐位与推荐位数据两张表。
还有一个推荐位的初始化脚本,代码实现如下:
<?php
namespace console\controllers;
use common\models\IdMaker;
use common\models\RecommendationSlot;
use Yii;
use yii\console\Controller;
use yii\console\ExitCode;
use yii\db\Exception;
use yii\helpers\BaseConsole;
use yii\helpers\Console;
class RecommendationSlotController extends Controller
{
/**
* 推荐位数据初始化
* @return void
* @throws Exception
*/
public function actionInit()
{
$now = date('Y-m-d H:i:s');
$data = [
[
'id' => '1001',
'alias' => 'sidebar-contact-1',
'name' => '获取专业会务管理解决方案',
'title' => '获取专业会务管理解决方案',
'description' => '',
'usage' => '',
],
[
'id' => '1002',
'alias' => 'sidebar-features',
'name' => '会务功能',
'title' => '会务功能',
'description' => '',
'usage' => '',
],
[
'id' => '1003',
'alias' => 'sidebar-products',
'name' => '产品服务',
'title' => '产品服务',
'description' => '',
'usage' => '',
],
[
'id' => '1004',
'alias' => 'sidebar-contact-2',
'name' => '我有需求立即联系',
'title' => '我有需求立即联系',
'description' => '',
'usage' => '',
],
[
'id' => '1006',
'alias' => 'setting-tabs',
'name' => '“真”零代码灵活搭建,专属系统灵活配置',
'title' => '“真”零代码灵活搭建,专属系统灵活配置',
'description' => '5分钟上手,1小时上线,个性化需求随时调整',
'usage' => '',
],
[
'id' => '1007',
'alias' => 'cases-with-image-and-content',
'name' => '300万用户在使用***,他们在竞争中脱颖而出',
'title' => '300万用户在使用***,他们在竞争中脱颖而出',
'description' => '一站式会务管理系统助力企业高效办会',
'usage' => '',
],
[
'id' => '1009',
'alias' => 'industry-carousels',
'name' => '行业资讯轮播图',
'title' => '新闻资讯轮播图',
'description' => '',
'usage' => '',
],
[
'id' => '1010',
'alias' => 'setting-tabs-mobile',
'name' => '“真”零代码灵活搭建,专属系统灵活配置(手机端)',
'title' => '',
'description' => '5分钟上手,1小时上线,个性化需求随时调整',
'usage' => '',
],
[
'id' => '1011',
'alias' => 'recommended-cases',
'name' => '领先企业都在用***',
'title' => '',
'description' => '无论是政务型会议、展会、学术会、经销商大会等等,都有您的同行已经加入我们',
'usage' => '首页的精彩案例',
],
[
'id' => '1012',
'alias' => 'industry-news',
'name' => '行业新闻资讯',
'title' => '',
'description' => '最新实时新闻,帮助主办及时了解行业动态',
'usage' => '首页的行业资讯',
],
[
'id' => '1013',
'alias' => 'links-recommended-for-you',
'name' => '猜你喜欢',
'title' => '',
'description' => '',
'usage' => '页面底部',
],
[
'id' => '1014',
'alias' => 'links-solutions',
'name' => ' 解决方案',
'title' => '',
'description' => '',
'usage' => '页面底部',
],
[
'id' => '1015',
'alias' => 'links-support',
'name' => '服务支持',
'title' => '',
'description' => '',
'usage' => '页面底部',
],
[
'id' => '1016',
'alias' => 'contact-image-1',
'name' => '微信公众号',
'title' => '',
'description' => '',
'usage' => '页面底部',
],
[
'id' => '1017',
'alias' => 'contact-image-2',
'name' => '客服微信',
'title' => '',
'description' => '',
'usage' => '页面底部',
],
[
'id' => '1018',
'alias' => 'links-resources',
'name' => '资源支持',
'title' => '',
'description' => '',
'usage' => '页面底部',
],
[
'id' => '1019',
'alias' => 'index-carousels',
'name' => '首页轮播图',
'title' => '首页轮播图',
'description' => '',
'usage' => '',
],
[
'id' => '1020',
'alias' => 'index-features',
'name' => '首页功能列表模块',
'title' => '',
'description' => '包括大会管理系统、活动管理系统、邀请函系统、信息查询系统、展会管理系统',
'usage' => '用于首页的多种功能满足您的日程所需',
],
[
'id' => '1021',
'alias' => 'index-convention-features',
'name' => '首页大会管理系统的功能列表模块',
'title' => '',
'description' => '适用于大型论坛、峰会、学术会议、政府大会、合作伙伴大会、经销商大会、产业大会、行业大会、发布会、招商会、培训会等会议场景。 支持自定义风格,功能模块丰富,注册即可使用!',
'usage' => '用于首页的大会管理系统',
],
[
'id' => '1022',
'alias' => 'convention-image-text',
'name' => '大会管理系统的详情页面的左图右文模块',
'title' => '',
'description' => '无限创建线上线下会议活动',
'usage' => '用于大会管理系统的详情页面',
],
[
'id' => '1023',
'alias' => 'feature-tabs',
'name' => '详情页-多种功能满足你日程所需',
'title' => '详情页-多种功能满足你日程所需',
'description' => '',
'usage' => '',
],
[
'id' => '1024',
'alias' => 'customers-with-logo',
'name' => '案例logo集合',
'title' => '服务千行百业,值得您信赖',
'description' => '',
'usage' => '',
],
];
foreach ($data as $row) {
$slot = RecommendationSlot::find()->where(['alias' => $row['alias']])->limit(1)->one();
if (!$slot) {
$slot = new RecommendationSlot();
$slot->created_at = $now;
echo "➕ 新增:{$row['alias']}\n";
} else {
echo "♻️ 更新:{$row['alias']}\n";
}
$slot->id = $row['id'];
$slot->alias = $row['alias'];
$slot->name = $row['name'];
$slot->title = $row['title'];
$slot->description = $row['description'];
$slot->usage = $row['usage'];
$slot->status = RecommendationSlot::STATUS_ENABLED;
$slot->updated_at = $now;
if (!$slot->save()) {
echo Console::error("❌ 保存失败:{$row['alias']}");
print_r($slot->getErrors());
}
}
echo Console::ansiFormat("✅ 初始化完成\n", [BaseConsole::FG_GREEN]);
}
}
实现了基于 alias 添加或者更新的逻辑,且 alias 与 id 固定了对应关系。
在代码中,硬编码获取推荐位数据时,基本上是基于 alias 获取。
现在存在一个问题,就是可能后台编辑推荐位时,允许 alias 为 null。那么在页面编辑器中,某一个页面元素数据源只能够关联上推荐位的 id,因为 alias 可能为 null 。
后台推荐位的 alias 可能会被修改,比如说 id = 1024 的 alias 为 customers-with-logo。后续可能 在后台需要将 id = 1024 的 alias 修改为 null,然后将 id = 1200 的 alias 修改为 customers-with-logo。此时需要在代码中,硬编码获取 alias 为 customers-with-logo 的数据。
现阶段感觉整体逻辑较为混乱,有无一个整体的清晰的逻辑结构可供参考?
2、最终初始化脚本调整如下
<?php
namespace console\controllers;
use common\models\IdMaker;
use common\models\RecommendationSlot;
use Yii;
use yii\console\Controller;
use yii\console\ExitCode;
use yii\db\Exception;
use yii\helpers\BaseConsole;
use yii\helpers\Console;
class RecommendationSlotController extends Controller
{
/**
* 推荐位数据初始化
* @return void
* @throws Exception
*/
public function actionInit()
{
$now = date('Y-m-d H:i:s');
$data = [
[
'id' => '1001',
'alias' => 'sidebar-contact-1',
'name' => '获取专业会务管理解决方案',
'title' => '获取专业会务管理解决方案',
'description' => '',
'usage' => '',
],
[
'id' => '1002',
'alias' => 'sidebar-features',
'name' => '会务功能',
'title' => '会务功能',
'description' => '',
'usage' => '',
],
[
'id' => '1003',
'alias' => 'sidebar-products',
'name' => '产品服务',
'title' => '产品服务',
'description' => '',
'usage' => '',
],
[
'id' => '1004',
'alias' => 'sidebar-contact-2',
'name' => '我有需求立即联系',
'title' => '我有需求立即联系',
'description' => '',
'usage' => '',
],
[
'id' => '1006',
'alias' => 'setting-tabs',
'name' => '“真”零代码灵活搭建,专属系统灵活配置',
'title' => '“真”零代码灵活搭建,专属系统灵活配置',
'description' => '5分钟上手,1小时上线,个性化需求随时调整',
'usage' => '',
],
[
'id' => '1007',
'alias' => 'cases-with-image-and-content',
'name' => '300万用户在使用***,他们在竞争中脱颖而出',
'title' => '300万用户在使用***,他们在竞争中脱颖而出',
'description' => '一站式会务管理系统助力企业高效办会',
'usage' => '',
],
[
'id' => '1009',
'alias' => 'industry-carousels',
'name' => '行业资讯轮播图',
'title' => '新闻资讯轮播图',
'description' => '',
'usage' => '',
],
[
'id' => '1010',
'alias' => 'setting-tabs-mobile',
'name' => '“真”零代码灵活搭建,专属系统灵活配置(手机端)',
'title' => '',
'description' => '5分钟上手,1小时上线,个性化需求随时调整',
'usage' => '',
],
[
'id' => '1011',
'alias' => 'recommended-cases',
'name' => '领先企业都在用***',
'title' => '',
'description' => '无论是政务型会议、展会、学术会、经销商大会等等,都有您的同行已经加入我们',
'usage' => '首页的精彩案例',
],
[
'id' => '1012',
'alias' => 'industry-news',
'name' => '行业新闻资讯',
'title' => '',
'description' => '最新实时新闻,帮助主办及时了解行业动态',
'usage' => '首页的行业资讯',
],
[
'id' => '1013',
'alias' => 'links-recommended-for-you',
'name' => '猜你喜欢',
'title' => '',
'description' => '',
'usage' => '页面底部',
],
[
'id' => '1014',
'alias' => 'links-solutions',
'name' => ' 解决方案',
'title' => '',
'description' => '',
'usage' => '页面底部',
],
[
'id' => '1015',
'alias' => 'links-support',
'name' => '服务支持',
'title' => '',
'description' => '',
'usage' => '页面底部',
],
[
'id' => '1016',
'alias' => 'contact-image-1',
'name' => '微信公众号',
'title' => '',
'description' => '',
'usage' => '页面底部',
],
[
'id' => '1017',
'alias' => 'contact-image-2',
'name' => '客服微信',
'title' => '',
'description' => '',
'usage' => '页面底部',
],
[
'id' => '1018',
'alias' => 'links-resources',
'name' => '资源支持',
'title' => '',
'description' => '',
'usage' => '页面底部',
],
[
'id' => '1019',
'alias' => 'index-carousels',
'name' => '首页轮播图',
'title' => '首页轮播图',
'description' => '',
'usage' => '',
],
[
'id' => '1020',
'alias' => 'index-features',
'name' => '首页功能列表模块',
'title' => '',
'description' => '包括大会管理系统、活动管理系统、邀请函系统、信息查询系统、展会管理系统',
'usage' => '用于首页的多种功能满足您的日程所需',
],
[
'id' => '1021',
'alias' => 'index-convention-features',
'name' => '首页大会管理系统的功能列表模块',
'title' => '',
'description' => '适用于大型论坛、峰会、学术会议、政府大会、合作伙伴大会、经销商大会、产业大会、行业大会、发布会、招商会、培训会等会议场景。 支持自定义风格,功能模块丰富,注册即可使用!',
'usage' => '用于首页的大会管理系统',
],
[
'id' => '1022',
'alias' => 'convention-image-text',
'name' => '大会管理系统的详情页面的左图右文模块',
'title' => '',
'description' => '无限创建线上线下会议活动',
'usage' => '用于大会管理系统的详情页面',
],
[
'id' => '1023',
'alias' => 'feature-tabs',
'name' => '详情页-多种功能满足你日程所需',
'title' => '详情页-多种功能满足你日程所需',
'description' => '',
'usage' => '',
],
[
'id' => '1832069240769958',
'alias' => 'customers-with-logo',
'name' => '案例logo集合',
'title' => '服务千行百业,值得您信赖',
'description' => '',
'usage' => '',
],
];
foreach ($data as $row) {
$existingSlot = RecommendationSlot::find()->where(['alias' => $row['alias']])->limit(1)->one();
$currentSlot = RecommendationSlot::find()->where(['id' => $row['id']])->limit(1)->one();
$now = date('Y-m-d H:i:s');
// 如果 alias 已存在,但不是当前 id,则需要迁移
if ($existingSlot && $existingSlot->id !== $row['id']) {
echo "🔁 alias '{$row['alias']}' 已被 id = {$existingSlot->id} 使用,准备迁移...\n";
// 清空旧 slot 的 alias
$existingSlot->alias = null;
$existingSlot->updated_at = $now;
if (!$existingSlot->save()) {
echo Console::error("❌ 清空旧 alias 失败:{$existingSlot->id}\n");
print_r($existingSlot->getErrors());
}
// 更新 recommendation_contents 中的 slot_id
Yii::$app->db->createCommand()->update(
'recommendation_contents',
['slot_id' => $row['id']],
['slot_id' => $existingSlot->id]
)->execute();
echo "✅ 已将 recommendation_contents.slot_id = {$existingSlot->id} 替换为 {$row['id']}\n";
}
if (!$currentSlot) {
$currentSlot = new RecommendationSlot();
$currentSlot->id = $row['id'];
$currentSlot->created_at = $now;
echo "➕ 新增:{$row['alias']} (id={$row['id']})\n";
} else {
echo "♻️ 更新:{$row['alias']} (id={$row['id']})\n";
}
$currentSlot->alias = $row['alias'];
$currentSlot->name = $row['name'];
$currentSlot->title = $row['title'];
$currentSlot->description = $row['description'];
$currentSlot->usage = $row['usage'];
$currentSlot->status = RecommendationSlot::STATUS_ENABLED;
$currentSlot->updated_at = $now;
if (!$currentSlot->save()) {
echo Console::error("❌ 保存失败:{$row['alias']} (id={$row['id']})\n");
print_r($currentSlot->getErrors());
}
}
echo Console::ansiFormat("✅ 初始化完成\n", [BaseConsole::FG_GREEN]);
}
}
近期评论