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

在 Yii 2.0 中,核心验证器:unique (唯一性) 支持多个模型与变量的实现

涉及至第 1 张表,企鹅号的文章:cpa_qq_article,需要验证其字段:title 的唯一性,表结构
1、涉及至第 1 张表,企鹅号的文章:cpa_qq_article,需要验证其字段:title 的唯一性,表结构如图1
涉及至第 1 张表,企鹅号的文章:cpa_qq_article,需要验证其字段:title 的唯一性,表结构
图1
2、涉及至第 2 张表,渠道的应用的任务:cpa_channel_app_task,字段:task_id 与 企鹅号的文章的字段:task_id 存在关联关系(多对一),字段:channel_app_source_uuid 为条件(变量、请求参数),字段:status 为条件(常量),表结构如图2
涉及至第 2 张表,渠道的应用的任务:cpa_channel_app_task,字段:task_id 与 企鹅号的文章的字段:task_id 存在关联关系(多对一),字段:channel_app_source_uuid 为条件(变量、请求参数),字段:status 为条件(常量),表结构
图2
3、filter:用于检查输入值唯一性必然会进行数据库查询,而该属性为用于进一步筛选该查询的过滤条件。样式为 function ($query) 的匿名函数, $query 参数为你希望在该函数内进行修改的 Query 对象。模型中的验证规则声明如下:


    /**
     * {@inheritdoc}
     */
    public function scenarios()
    {
        $scenarios = parent::scenarios();
        $scenarios[self::SCENARIO_CREATE] = ['group_id', 'article_category_id', 'title', 'author', 'source_article_id'];

        return $scenarios;
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        $rules = [
            ['title', 'unique', 'filter' => function ($query) {
                /* @var $query ChannelAppTaskQuery */
                $query->joinWith('channelAppTask', false)->andWhere([ChannelAppTask::tableName() . '.status' => ChannelAppTask::STATUS_PLATFORM_PUBLISHED]);
            }, 'on' => self::SCENARIO_CREATE],
        ];
        $parentRules = parent::rules();

        return ArrayHelper::merge($rules, $parentRules);
    }

    /*
     * 声明了一个渠道的应用的任务关联
     */
    public function getChannelAppTask()
    {
        return $this->hasOne(ChannelAppTask::className(), ['task_id' => 'task_id']);
    }


4、验证请求参数时,生成的 SQL 如下:


SELECT EXISTS(SELECT `cpa_qq_article`.* FROM `cpa_qq_article` LEFT JOIN `cpa_channel_app_task` ON `cpa_qq_article`.`task_id` = `cpa_channel_app_task`.`task_id` WHERE (`cpa_qq_article`.`title`='未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化。') AND (`cpa_channel_app_task`.`status`=6))


5、请求参数中,存在 channel_app_source_uuids 字段,其值为数组:[“8d72b7cc2ac911eab85a54ee75d2ebc1”, “18cf06d22ac911eaa31854ee75d2ebc1”],需要将 channel_app_source_uuids 的值做为条件应用于唯一性验证的查询条件中。在执行模型的验证之前,赋值给应用的全局参数变量 Yii::$app->params。如图3
请求参数中,存在 channel_app_source_uuids 字段,其值为数组:["8d72b7cc2ac911eab85a54ee75d2ebc1", "18cf06d22ac911eaa31854ee75d2ebc1"],需要将 channel_app_source_uuids 的值做为条件应用于唯一性验证的查询条件中。在执行模型的验证之前,赋值给应用的全局参数变量 Yii::$app->params。
图3


$requestParams = Yii::$app->getRequest()->getBodyParams();
Yii::$app->params['channelAppSourceUuids'] = $requestParams['channel_app_source_uuids'];


6、现在可在验证规则中使用 Yii::$app->params,模型中的验证规则声明调整如下:


    /**
     * @inheritdoc
     */
    public function rules()
    {
        $rules = [
            ['title', 'unique', 'filter' => function ($query) {
                /* @var $query ChannelAppTaskQuery */
                $query->joinWith('channelAppTask', false)->andWhere(['and', ['in', ChannelAppTask::tableName() . '.channel_app_source_uuid', Yii::$app->params['channelAppSourceUuids']], [ChannelAppTask::tableName() . '.status' => ChannelAppTask::STATUS_PLATFORM_PUBLISHED]]);
            }, 'on' => self::SCENARIO_CREATE],
        ];
        $parentRules = parent::rules();

        return ArrayHelper::merge($rules, $parentRules);
    }


7、验证请求参数时,生成的 SQL 如下,请求参数已经应用于查询条件中,符合预期


SELECT EXISTS(SELECT `cpa_qq_article`.* FROM `cpa_qq_article` LEFT JOIN `cpa_channel_app_task` ON `cpa_qq_article`.`task_id` = `cpa_channel_app_task`.`task_id` WHERE (`cpa_qq_article`.`title`='未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化。') AND ((`cpa_channel_app_task`.`channel_app_source_uuid` IN ('8d72b7cc2ac911eab85a54ee75d2ebc1', '18cf06d22ac911eaa31854ee75d2ebc1')) AND (`cpa_channel_app_task`.`status`=6)))


8、核心验证器:unique (唯一性) 支持多个模型与变量的实现,验证失败时,响应如下,如图4
核心验证器:unique (唯一性) 支持多个模型与变量的实现,验证失败时,响应如下
图4


{
    "code": 226004,
    "message": "数据验证失败:标题的值\"未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化。\"已经被占用了。"
}


PHP / Laravel / Yii2 老项目维护与长期技术支持

如果你的 PHP / Laravel / Yii2 项目已经上线,但遇到原开发离职、Bug 长期无人修复、接口不稳定、性能下降、代码难以接手等问题,可以联系我做一次远程技术排查。

适合以下情况:
✅ 老旧 PHP 系统无人维护
✅ Laravel / Yii2 项目 Bug 修复
✅ 后台管理系统小功能迭代
✅ RESTful API 接口排查
✅ MySQL / Redis / Nginx 性能问题
✅ 长期远程兼职维护

可先从一次小问题开始:
✅ 线上报错排查
✅ 接口异常分析
✅ 慢查询与性能瓶颈定位
✅ 代码结构初步评估
✅ 部署环境与日志检查

如需咨询,请联系我,并注明:PHP 维护咨询

联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理