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

Implementing the Unique Core Validator for Multiple Models and Variables in Yii 2.0

Involving the first table, Penguin account articles: cpa_qq_article, the uniqueness of its field: title needs to be validated. The table structure

1. Involving the first table, Penguin account articles: cpa_qq_article, the uniqueness of its field: title needs to be validated. The table structure is shown in Figure 1.

Involving the first table, Penguin account articles: cpa_qq_article, the uniqueness of its field: title needs to be validated. The table structure
Figure 1

2. Involving the second table, channel application tasks: cpa_channel_app_task. The field: task_id has a many-to-one relationship with the field: task_id in the Penguin account articles. The field: channel_app_source_uuid serves as a condition (variable, request parameter), and the field: status serves as a condition (constant). The table structure is shown in Figure 2.

Involving the second table, channel application tasks: cpa_channel_app_task. The field: task_id has a many-to-one relationship with the field: task_id in the Penguin account articles. The field: channel_app_source_uuid serves as a condition (variable, request parameter), and the field: status serves as a condition (constant). The table structure
Figure 2

3. filter: Validating the uniqueness of an input value inevitably requires a database query, and this property provides additional filter conditions to further refine that query. It takes the form of an anonymous function, function ($query), where the $query parameter is the Query object you wish to modify within the function. The validation rules declared in the model are as follows:

PHP

    /**
     * {@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. When validating the request parameters, the generated SQL is as follows:

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. Among the request parameters, there is a channel_app_source_uuids field, whose value is an array: [“8d72b7cc2ac911eab85a54ee75d2ebc1”, “18cf06d22ac911eaa31854ee75d2ebc1”]. The value of channel_app_source_uuids needs to be applied as a condition to the uniqueness validation query. Before executing the model’s validation, assign it to the application’s global parameter variable Yii::$app->params. As shown in Figure 3.

Among the request parameters, there is a channel_app_source_uuids field, whose value is an array: ["8d72b7cc2ac911eab85a54ee75d2ebc1", "18cf06d22ac911eaa31854ee75d2ebc1"]. The value of channel_app_source_uuids needs to be applied as a condition to the uniqueness validation query. Before executing the model's validation, assign it to the application's global parameter variable Yii::$app->params.
Figure 3
PHP

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

6. Now Yii::$app->params can be used in the validation rules. The validation rules declared in the model are adjusted as follows:

PHP

    /**
     * @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. When validating the request parameters, the generated SQL is as follows. The request parameters have been applied to the query conditions, which meets expectations.

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. The core validator: unique (uniqueness) supports an implementation with multiple models and variables. When validation fails, the response is as follows, as shown in Figure 4.

The core validator: unique (uniqueness) supports an implementation with multiple models and variables. When validation fails, the response is as follows
Figure 4
JSON

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

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

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

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

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

关于我  ·  GitHub  ·  邮件联系