没有不值得去解决的问题,也没有不值得去学习的技术!

Recommended Slot Aliases May Change or Become Null, Breaking Hardcoded Lookups in Business Logic

1. — `official-website-management-system`.recommendation_slots definition

SQL
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;


There are currently two tables: one for recommendation slots and another for recommendation slot data.
There is also an initialization script for recommendation slots, implemented as follows:

PHP
<?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]);
    }
}

It implements the logic for adding or updating based on the alias, and the mapping between the alias and the id is fixed.

In the code, when hardcoding the retrieval of recommendation slot data, it is essentially fetched based on the alias.

A current issue is that when editing a recommendation slot in the backend, the alias is allowed to be null. Consequently, in the page editor, a page element’s data source can only be associated with the recommendation slot’s id, because the alias might be null.

The alias of a backend recommendation slot might be modified. For example, the alias for id = 1024 is customers-with-logo. Later, it may be necessary in the backend to change the alias for id = 1024 to null, and then change the alias for id = 1200 to customers-with-logo. In this case, the code needs to hardcode the retrieval of the data where the alias is customers-with-logo.

At this stage, the overall logic feels rather confusing. Is there a clear, overall logical structure that can be used as a reference?

2. The final initialization script is adjusted as follows

PHP
<?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]);
    }
}
 
 

关于作者 · 持续学习与技术实践

我是一名拥有 15 年以上开发经验的技术从业者,自 2013 年起持续运营个人技术博客,记录工作与个人项目中遇到的真实问题,以及解决问题过程中的探索、实践和思考。

除了技术写作,我也在持续开发和维护自己的独立项目,探索新技术和新工具在实际场景中的应用。我始终相信,没有不值得去解决的问题,也没有不值得去学习的技术。

如果这篇文章对你有所帮助,欢迎浏览博客中的其他文章,也欢迎交流技术经验与想法。

关于我  ·  GitHub  ·  邮件联系