任务的入库成功、入库失败,皆需要能够查询到发布记录的设计与实现(在 Yii 2.0 中具体实现) (一)

1、获取企鹅号的应用的任务列表,列表为空,如图1

获取企鹅号的应用的任务列表,列表为空

图1

2、发布文章类型:标准(普通、图文)的文章,发布成功(即入库成功),查看发布任务的 SQL 语句,如图2

发布文章类型:标准(普通、图文)的文章,发布成功(即入库成功),查看发布任务的 SQL 语句

图2

Begin transaction

INSERT INTO `cpa_task` (`group_id`, `source`, `source_uuid`, `source_pub_user_id`, `source_callback_url`, `channel_id`, `channel_code`, `channel_type_id`, `channel_type_code`, `status`, `created_at`, `updated_at`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 'spider', '825e6d5e36468cc4bf536799ce3565cf', '3', 'http://scms.wjdev.chinamcloud.cn/api/thirdPush/callBack', 1, 'qq', 1, 'qq_cw', 1, 1577686722, 1577686722)

INSERT INTO `cpa_channel_app_task` (`channel_id`, `channel_code`, `channel_type_id`, `channel_type_code`, `channel_app_source_id`, `channel_app_source_uuid`, `task_id`, `have_pub_number`, `status`, `created_at`, `updated_at`, `uuid`) VALUES (1, 'qq', 1, 'qq_cw', 14, '8d72b7cc2ac911eab85a54ee75d2ebc1', 1, 3, 1, 1577686722, 1577686722, '3a1d31262acc11ea9f5754ee75d2ebc1')

INSERT INTO `cpa_qq_cw_app_task` (`channel_app_task_id`, `channel_app_task_uuid`, `qq_cw_app_id`, `task_id`, `platform_status`, `status`, `created_at`, `updated_at`) VALUES (1, '3a1d31262acc11ea9f5754ee75d2ebc1', 2, 1, 0, 1, 1577686722, 1577686722)

INSERT INTO `cpa_qq_article` (`group_id`, `article_category_id`, `title`, `author`, `source_article_id`, `qq_app_type`, `article_type_id`, `qq_article_type_id`, `qq_article_category_id`, `task_id`, `status`, `created_at`, `updated_at`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 15, '2019 年 22 款最佳软件开发工具', 'Guru99', 1, 'cw', 1, 1, 18, 1, 1, 1577686722, 1577686722)

INSERT INTO `cpa_qq_article_normal` (`content`, `cover_pic`, `cover_type`, `tag`, `apply`, `original_platform`, `original_url`, `original_author`, `qq_article_id`, `category`, `status`, `created_at`, `updated_at`) VALUES ('市面上有海量的软件开发工具,因此,选择最佳软件开发工具可能是一项挑战。本文是 22 款顶级软件开发工具的精选列表。', 'https://static001.infoq.cn/resource/image/90/6a/9054bf66f3ce4d0a4822a1b7398c566a.png', 1, '2019,22,最佳,软件,开发工具', 0, 0, '', '', 1, 18, 1, 1577686722, 1577686722)

Commit transaction

3、获取企鹅号的应用的任务列表,列表中存在 1 条记录,查看获取企鹅号的应用的任务列表的 SQL 语句,如图3

获取企鹅号的应用的任务列表,列表中存在 1 条记录,查看获取企鹅号的应用的任务列表的 SQL 语句

图3

SELECT `cpa_channel_app_task`.*, `cpa_task`.`group_id`, `cpa_task`.`source`, `cpa_task`.`source_uuid`, `cpa_task`.`source_pub_user_id`, `cpa_qq_cw_app`.`penguin_name`, `cpa_channel_app_task`.`status`, `cpa_article_type`.`code` AS `article_type_code`, `cpa_article_type`.`name` AS `article_type_name`, `cpa_qq_article`.`article_category_id`, `cpa_qq_article`.`title` AS `article_title`, `cpa_qq_article`.`author` AS `article_author`, `cpa_qq_article`.`source_article_id`, `cpa_qq_transaction`.`article_url`, `cpa_pub_log`.`code` AS `pub_log_code`, `cpa_pub_log`.`message` AS `pub_log_message` FROM `cpa_channel_app_task` LEFT JOIN `cpa_task` ON `cpa_channel_app_task`.`task_id` = `cpa_task`.`id` LEFT JOIN `cpa_qq_article` ON `cpa_task`.`id` = `cpa_qq_article`.`task_id` LEFT JOIN `cpa_article_type` ON `cpa_qq_article`.`article_type_id` = `cpa_article_type`.`id` LEFT JOIN `cpa_qq_cw_app_task` ON `cpa_channel_app_task`.`id` = `cpa_qq_cw_app_task`.`channel_app_task_id` LEFT JOIN `cpa_qq_cw_app` ON `cpa_qq_cw_app_task`.`qq_cw_app_id` = `cpa_qq_cw_app`.`id` LEFT JOIN `cpa_pub_log` ON `cpa_channel_app_task`.`id` = `cpa_pub_log`.`channel_app_task_id` LEFT JOIN `cpa_qq_transaction` ON `cpa_qq_cw_app_task`.`id` = `cpa_qq_transaction`.`qq_app_task_id` AND `cpa_qq_transaction`.`type` = '1' WHERE ((`cpa_channel_app_task`.`is_deleted`=0) AND (`cpa_task`.`is_deleted`=0) AND (`cpa_qq_article`.`is_deleted`=0) AND (`cpa_article_type`.`is_deleted`=0) AND (`cpa_qq_cw_app_task`.`is_deleted`=0) AND (`cpa_qq_cw_app`.`is_deleted`=0)) AND (`cpa_task`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') ORDER BY `cpa_task`.`id` DESC LIMIT 20

4、发布文章类型:标准(普通、图文)的文章,发布失败(即未入库,因为数据验证失败),由步骤 2 可知,即使数据验证成功(),5 条插入 SQL 语句在 1 个事务中,只要其中任意 1 条 SQL 执行失败,便会回滚,入库失败。如图4

发布文章类型:标准(普通、图文)的文章,发布失败(即未入库,因为数据验证失败),由步骤 2 可知,即使数据验证成功(),5 条插入 SQL 语句在 1 个事务中,只要其中任意 1 条 SQL 执行失败,便会回滚,入库失败。

图4

5、获取企鹅号的应用的任务列表,列表中存在 1 条记录。但是,客户端希望能够获取到 2 条记录,因为,从客户端的用户方面来看待此问题,实际上是已经发布过 2 次任务,而不是 1 次。现阶段的实现方案有 2 种,第 1 种是渠道发布本身维持现有的业务逻辑不变化,发布任务的记录在客户端数据库中冗余再存储;第 2 种方案是渠道发布任务的入库成功、入库失败,皆需要能够查询到发布记录,客户端不做处理,仅直接获取渠道发布的任务列表。最终决定采用第 2 种方案,原因在于任务记录仅存在一个数据源,有利于保证唯一性与简单性,避免多个数据源导致的冗余度与复杂性。如图5

获取企鹅号的应用的任务列表,列表中存在 1 条记录。但是,客户端希望能够获取到 2 条记录,因为,从客户端的用户方面来看待此问题,实际上是已经发布过 2 次任务,而不是 1 次。现阶段的实现方案有 2 种,第 1 种是渠道发布本身维持现有的业务逻辑不变化,发布任务的记录在客户端数据库中冗余再存储;第  2 种方案是渠道发布任务的入库成功、入库失败,皆需要能够查询到发布记录,客户端不做处理,仅直接获取渠道发布的任务列表。最终决定采用第 2 种方案,原因在于任务记录仅存在一个数据源,有利于保证唯一性与简单性,避免多个数据源导致的冗余度与复杂性。

图5

6、如何来实现即使入库失败,也能够查询到发布记录呢?前提是必须要保证请求的数据入库成功,但是理论上是无法实现的。比如说:请求数据中的标题长度超出表:cpa_qq_article 的字段:title 的长度,即使在执行插入 SQL 之前不做数据验证,SQL 语句也会执行失败,进而回滚。如图6

如何来实现即使入库失败,也能够查询到发布记录呢?前提是必须要保证请求的数据入库成功,但是理论上是无法实现的。比如说:请求数据中的标题长度超出表:cpa_qq_article 的字段:title 的长度,即使在执行插入 SQL 之前不做数据验证,SQL 语句也会执行失败,进而回滚。

图6

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['title'], 'string', 'max' => 255], // 删除掉,不做数据验证
        ];
    }
{
"name": "Database Exception",
"message": "SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'title' at row 1/nThe SQL being executed was: INSERT INTO `cpa_qq_article` (`group_id`, `article_category_id`, `title`, `author`, `source_article_id`, `qq_app_type`, `article_type_id`, `qq_article_type_id`, `qq_article_category_id`, `task_id`, `status`, `created_at`, `updated_at`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 15, '未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化。北京时间 2019 年 12 月 28 日,1999-2019“星光中国芯工程”创新成果与展望报告会在人民大会堂举行。会议回顾和总结了“星光中国芯工程”20 年来在核心技术自主创新、在研发成果大规模产业化、以及在满足国家重大工程技术需求方面取得的重要进展和成功经验,并对“星光中国芯工程”未来发展进行了规划和展望。中国工程院院士、“星光中国芯工程”总指挥、中星微电子集团创建人兼首席科学家邓中翰作了“星光中国芯工程”20 年成果与展望工作报告,报告中,邓中翰表示,在物理层面智能芯片的发展已经受到了物理规律的限制,看似已经接近了极限的时候,在信息层面的技术创新还远远没有碰到天花板。1999 年,邓中翰等一批海外爱国博士企业家回国承担并启动实施“星光中国芯工程”,在北京中关村设立中星微电子公司,致力于超大规模集成电路芯片的研发、设计及产业化工作。2001 年,中国第一颗百万门级超大规模数字多媒体芯片“星光一号”诞生。其后数年间,“星光多媒体”系列芯片被苹果、三星、飞利浦、惠普、LG、索尼、戴尔等国外知名品牌规模采用,占领了全球计算机图像输入芯片 60% 以上的市场份额,彻底结束了中国无“芯”的历史。', '刘燕', 1, 'cw', 1, 1, 18, 4, 1, 1577692119, 1577692119)",
"code": 22001,
"type": "yii//db//Exception",
"file": "E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//Schema.php",
"line": 674,
"stack-trace": [
"#0 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//Command.php(1295): yii//db//Schema->convertException(Object(PDOException), 'INSERT INTO `cp...')",
"#1 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//Command.php(1091): yii//db//Command->internalExecute('INSERT INTO `cp...')",
"#2 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//Schema.php(432): yii//db//Command->execute()",
"#3 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//ActiveRecord.php(600): yii//db//Schema->insert('{{%qq_article}}', Array)",
"#4 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//ActiveRecord.php(566): yii//db//ActiveRecord->insertInternal(NULL)",
"#5 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//BaseActiveRecord.php(678): yii//db//ActiveRecord->insert(false, NULL)",
"#6 E://wwwroot//channel-pub-api//common//services//QqArticleService.php(88): yii//db//BaseActiveRecord->save(false)",
"#7 E://wwwroot//channel-pub-api//qq//services//QqArticleService.php(182): common//services//QqArticleService->create(Object(qq//modules//v1//models//QqArticle), false)",
"#8 E://wwwroot//channel-pub-api//qq//rests//article//StandardCreateAction.php(342): qq//services//QqArticleService->standardCreate(Object(common//logics//Channel), Object(common//logics//ChannelType), Array, Array, Object(common//logics//ArticleType), Object(common//logics//QqArticleType), Object(common//logics//QqArticleCategoryNormal), Object(qq//models//Task), Object(qq//modules//v1//models//QqArticle), Object(qq//models//QqArticleNormal))",
"#9 [internal function]: qq//rests//article//StandardCreateAction->run()",
"#10 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//base//Action.php(94): call_user_func_array(Array, Array)",
"#11 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//base//Controller.php(157): yii//base//Action->runWithParams(Array)",
"#12 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//base//Module.php(528): yii//base//Controller->runAction('standard-create', Array)",
"#13 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//web//Application.php(103): yii//base//Module->runAction('v1/article/stan...', Array)",
"#14 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//base//Application.php(386): yii//web//Application->handleRequest(Object(yii//web//Request))",
"#15 E://wwwroot//channel-pub-api//qq//web//index.php(17): yii//base//Application->run()",
"#16 {main}"
],
"error-info": [
"22001",
1406,
"Data too long for column 'title' at row 1"
],
"previous": {
"name": "Exception",
"message": "SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'title' at row 1",
"code": "22001",
"type": "PDOException",
"file": "E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//Command.php",
"line": 1290,
"stack-trace": [
"#0 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//Command.php(1290): PDOStatement->execute()",
"#1 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//Command.php(1091): yii//db//Command->internalExecute('INSERT INTO `cp...')",
"#2 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//Schema.php(432): yii//db//Command->execute()",
"#3 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//ActiveRecord.php(600): yii//db//Schema->insert('{{%qq_article}}', Array)",
"#4 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//ActiveRecord.php(566): yii//db//ActiveRecord->insertInternal(NULL)",
"#5 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//db//BaseActiveRecord.php(678): yii//db//ActiveRecord->insert(false, NULL)",
"#6 E://wwwroot//channel-pub-api//common//services//QqArticleService.php(88): yii//db//BaseActiveRecord->save(false)",
"#7 E://wwwroot//channel-pub-api//qq//services//QqArticleService.php(182): common//services//QqArticleService->create(Object(qq//modules//v1//models//QqArticle), false)",
"#8 E://wwwroot//channel-pub-api//qq//rests//article//StandardCreateAction.php(342): qq//services//QqArticleService->standardCreate(Object(common//logics//Channel), Object(common//logics//ChannelType), Array, Array, Object(common//logics//ArticleType), Object(common//logics//QqArticleType), Object(common//logics//QqArticleCategoryNormal), Object(qq//models//Task), Object(qq//modules//v1//models//QqArticle), Object(qq//models//QqArticleNormal))",
"#9 [internal function]: qq//rests//article//StandardCreateAction->run()",
"#10 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//base//Action.php(94): call_user_func_array(Array, Array)",
"#11 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//base//Controller.php(157): yii//base//Action->runWithParams(Array)",
"#12 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//base//Module.php(528): yii//base//Controller->runAction('standard-create', Array)",
"#13 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//web//Application.php(103): yii//base//Module->runAction('v1/article/stan...', Array)",
"#14 E://wwwroot//channel-pub-api//vendor//yiisoft//yii2//base//Application.php(386): yii//web//Application->handleRequest(Object(yii//web//Request))",
"#15 E://wwwroot//channel-pub-api//qq//web//index.php(17): yii//base//Application->run()",
"#16 {main}"
]
}
}
Begin transaction
INSERT INTO `cpa_task` (`group_id`, `source`, `source_uuid`, `source_pub_user_id`, `source_callback_url`, `channel_id`, `channel_code`, `channel_type_id`, `channel_type_code`, `status`, `created_at`, `updated_at`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 'spider', '825e6d5e36468cc4bf536799ce3565cf', '3', 'http://scms.wjdev.chinamcloud.cn/api/thirdPush/callBack', 1, 'qq', 1, 'qq_cw', 1, 1577692119, 1577692119)
INSERT INTO `cpa_channel_app_task` (`channel_id`, `channel_code`, `channel_type_id`, `channel_type_code`, `channel_app_source_id`, `channel_app_source_uuid`, `task_id`, `have_pub_number`, `status`, `created_at`, `updated_at`, `uuid`) VALUES (1, 'qq', 1, 'qq_cw', 14, '8d72b7cc2ac911eab85a54ee75d2ebc1', 4, 3, 1, 1577692119, 1577692119, 'caf880d62ad811ea88f654ee75d2ebc1')
INSERT INTO `cpa_qq_cw_app_task` (`channel_app_task_id`, `channel_app_task_uuid`, `qq_cw_app_id`, `task_id`, `platform_status`, `status`, `created_at`, `updated_at`) VALUES (4, 'caf880d62ad811ea88f654ee75d2ebc1', 2, 4, 0, 1, 1577692119, 1577692119)
INSERT INTO `cpa_qq_article` (`group_id`, `article_category_id`, `title`, `author`, `source_article_id`, `qq_app_type`, `article_type_id`, `qq_article_type_id`, `qq_article_category_id`, `task_id`, `status`, `created_at`, `updated_at`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 15, '未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化。北京时间 2019 年 12 月 28 日,1999-2019“星光中国芯工程”创新成果与展望报告会在人民大会堂举行。会议回顾和总结了“星光中国芯工程”20 年来在核心技术自主创新、在研发成果大规模产业化、以及在满足国家重大工程技术需求方面取得的重要进展和成功经验,并对“星光中国芯工程”未来发展进行了规划和展望。中国工程院院士、“星光中国芯工程”总指挥、中星微电子集团创建人兼首席科学家邓中翰作了“星光中国芯工程”20 年成果与展望工作报告,报告中,邓中翰表示,在物理层面智能芯片的发展已经受到了物理规律的限制,看似已经接近了极限的时候,在信息层面的技术创新还远远没有碰到天花板。1999 年,邓中翰等一批海外爱国博士企业家回国承担并启动实施“星光中国芯工程”,在北京中关村设立中星微电子公司,致力于超大规模集成电路芯片的研发、设计及产业化工作。2001 年,中国第一颗百万门级超大规模数字多媒体芯片“星光一号”诞生。其后数年间,“星光多媒体”系列芯片被苹果、三星、飞利浦、惠普、LG、索尼、戴尔等国外知名品牌规模采用,占领了全球计算机图像输入芯片 60% 以上的市场份额,彻底结束了中国无“芯”的历史。', '刘燕', 1, 'cw', 1, 1, 18, 4, 1, 1577692119, 1577692119)
Roll back transaction

7、实施新的数据库迁移,新建表:预发布日志(pre_pub_log),最终的表结构,表中的字段类型与任务表中的字段类型保持一致,但是字符串类型的字段,加大其长度,尽可能提升其入库成功率,基于接口动作方法的返回码,当返回码不等于 10000 时,插入记录,如图7

实施新的数据库迁移,新建表:预发布日志(pre_pub_log),最终的表结构,表中的字段类型与任务表中的字段类型保持一致,但是字符串类型的字段,加大其长度,尽可能提升其入库成功率,基于接口动作方法的返回码,当返回码不等于 10000 时,插入记录

图7

8、实现预发布日志服务,创建预发布日志,尽最大可能避免抛出异常,一旦抛出异常,则无法插入记录至预发布日志。common/services/PrePubLogService.php

<?php
/**
* Created by PhpStorm.
* User: Qiang Wang
* Date: 2020/01/03
* Time: 17:51
*/
namespace common/services;
use Yii;
use common/logics/ArticleType;
use common/logics/Channel;
use common/logics/ChannelAppSource;
use common/logics/PrePubLog;
use common/behaviors/UUIDBehavior;
use yii/db/Exception;
use yii/helpers/ArrayHelper;
class PrePubLogService extends Service
{
/**
* 批量创建预发布日志
* @param string $groupId 租户ID
* 格式如下:015ce30b116ce86058fa6ab4fea4ac63
*
* @param int $code 返回码
* 格式如下:226004
*
* @param string $message 说明
* 格式如下:数据验证失败:文章封面图不能为空。
*
* @param string $channelCode 渠道代码
* 格式如下:qq
*
* @param string $type 任务类型,preview:预览;pub:发布;revoke:撤回
* 格式如下:pub
*
* @param string $articleTypeCode 文章类型代码
* 格式如下:standard
*
* @param array $requestParams 请求参数
* 格式如下:
* [
*     'channel_app_source_uuids' => [
*         '18cf06d22ac911eaa31854ee75d2ebc0',
*         '8d72b7cc2ac911eab85a54ee75d2ebc1',
*     ],
*     'source' => 'spider',
*     'source_uuid' => '825e6d5e36468cc4bf536799ce3565cf',
*     'source_pub_user_id' => 3,
*     'source_callback_url' => 'http://scms.wjdev.chinamcloud.cn/api/thirdPush/callBack',
*     'article_category_id' => 15,
*     'title' => '未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化',
*     'author' => '刘燕',
*     'source_article_id' => 1,
*     ...
* ]
*
* @return int number of rows affected by the execution.
* @throws Exception execution failed
*/
public function createMultiple($groupId, $code, $message, $channelCode, $type, $articleTypeCode, $requestParams)
{
// 基于代码查找单个资源(渠道)
$channelItem = Channel::findOneByCode($channelCode);
if (isset($channelItem)) {
$channelId = $channelItem->id;
} else {
$channelId = 0;
}
// 基于代码查找单个资源(文章类型)
$articleTypeItem = ArticleType::findOneByCode($articleTypeCode);
if (isset($articleTypeItem)) {
$articleTypeId = $articleTypeItem->id;
$articleTypeName = $articleTypeItem->name;
} else {
$articleTypeId = 0;
$articleTypeName = '';
}
// 渠道的应用的来源ID(UUID)
$channelAppSourceUuids = $requestParams['channel_app_source_uuids'] ?? []; // 渠道的应用的来源ID(UUID)
if (!is_array($channelAppSourceUuids)) {
$channelAppSourceUuids = [$channelAppSourceUuids];
}
$time = time();
// 公共字段列表
$prePubLogCommonFields = [
'group_id' => $groupId,
'channel_id' => $channelId,
'channel_code' => $channelCode,
'type' => $type,
'article_type_id' => $articleTypeId,
'article_type_code' => $articleTypeCode,
'article_type_name' => $articleTypeName,
'article_category_id' => $requestParams['article_category_id'] ?? 0,
'article_title' => $requestParams['title'] ?? '',
'article_author' => $requestParams['author'] ?? '',
'source' => $requestParams['source'] ?? '',
'source_uuid' => $requestParams['source_uuid'] ?? '',
'source_pub_user_id' => $requestParams['source_pub_user_id'] ?? 0,
'source_callback_url' => $requestParams['source_callback_url'] ?? '',
'source_article_id' => $requestParams['source_article_id'] ?? '',
'pub_log_code' => $code,
'pub_log_message' => $message,
'pub_log_body' => serialize($requestParams),
'status' => PrePubLog::STATUS_PUBLISH_ERROR,
'is_deleted' => PrePubLog::IS_DELETED_NO,
'created_at' => $time,
'updated_at' => $time,
'deleted_at' => PrePubLog::DELETED_AT_DEFAULT,
];
foreach ($channelAppSourceUuids as $channelAppSourceUuid) {
$uuidBehavior = new UUIDBehavior();
$uuid = $uuidBehavior->createUUID(); // 预发布日志ID(UUID)
// 基于UUID查找单个资源
$channelAppSourceItem = ChannelAppSource::findOneByUuid($channelAppSourceUuid);
if (isset($channelAppSourceItem)) {
$prePubLogRows[] = ArrayHelper::merge($prePubLogCommonFields, [
'uuid' => $uuid,
'channel_type_id' => $channelAppSourceItem->channel_type_id,
'channel_type_code' => $channelAppSourceItem->channel_type_code,
'channel_app_source_id' => $channelAppSourceItem->id,
'channel_app_source_uuid' => $channelAppSourceItem->uuid,
]);
} else {
$prePubLogRows[] = ArrayHelper::merge($prePubLogCommonFields, [
'uuid' => $uuid,
'channel_type_id' => 0,
'channel_type_code' => '',
'channel_app_source_id' => 0,
'channel_app_source_uuid' => $channelAppSourceUuid,
]);
}
}
/* 创建MySQL模型(预发布日志) */
$prePubLogTable = PrePubLog::tableName();
if (isset($prePubLogRows)) {
$prePubLogColumns = array_keys($prePubLogRows[0]);
return Yii::$app->db->createCommand()->batchInsert($prePubLogTable, $prePubLogColumns, $prePubLogRows)->execute();
}
return 0;
}
}

9、创建预发布日志过滤器:qq/filters/PrePubLogFilter.php,继承 yii/base/ActionFilter 类并覆盖 afterAction() 方法来创建动作的过滤器,在动作执行之后执行。判断返回码,如果不等于 10000,则操作数据(批量创建预发布日志)。

<?php
/**
* Created by PhpStorm.
* User: Qiang Wang
* Date: 2019/12/31
* Time: 17:25
*/
namespace qq/filters;
use Yii;
use qq/models/ArticleType;
use qq/models/Channel;
use qq/models/Task;
use qq/services/PrePubLogService;
use yii/base/ActionFilter;
use yii/base/InvalidConfigException;
use yii/db/Exception;
/**
* 预发布日志过滤器
* @package qq/filters
*
* @author Qiang Wang <shuijingwanwq@163.com>
* @since 1.0
*/
class PrePubLogFilter extends ActionFilter
{
/**
* {@inheritdoc}
* @throws InvalidConfigException if a registered parser does not implement the [[RequestParserInterface]].
* @throws Exception execution failed
*/
public function afterAction($action, $result)
{
if ($result['code'] !== 10000) {
$groupId = Yii::$app->params['groupId']; // 租户ID
$channelCode = Channel::CODE_QQ; // 渠道代码
$type = Task::TYPE_PUB; // 任务类型,preview:预览;pub:发布;revoke:撤回
$articleTypeCode = ArticleType::CODE_STANDARD; // 文章类型代码
if ($action->id == 'video-create') {
$articleTypeCode = ArticleType::CODE_VIDEO;
} elseif ($action->id == 'images-create') {
$articleTypeCode = ArticleType::CODE_IMAGES;
}
// 返回所有请求参数
$requestParams = Yii::$app->getRequest()->getBodyParams();
/* 操作数据(批量创建预发布日志) */
$prePubLogService = new PrePubLogService();
$prePubLogService->createMultiple($groupId, $result['code'], $result['message'], $channelCode, $type, $articleTypeCode, $requestParams);
}
return parent::afterAction($action, $result);
}
}

10、使用过滤器,过滤器本质上是一类特殊的行为, 所以使用过滤器和使用行为一样。 可以在控制器类中覆盖它的 behaviors() 方法来声明过滤器,编辑控制器:qq/controllers/ArticleController.php,配置 only 属性明确指定控制器应用到哪些动作。

<?php
/**
* Created by PhpStorm.
* User: Qiang Wang
* Date: 2018/08/31
* Time: 10:43
*/
namespace qq/controllers;
use qq/filters/PrePubLogFilter;
use yii/rest/ActiveController;
/**
* Class ArticleController
* @package qq/controllers
*
* @author Qiang Wang <shuijingwanwq@163.com>
* @since 1.0
*/
class ArticleController extends ActiveController
{
public $serializer = [
'class' => 'qq/rests/article/Serializer',
'collectionEnvelope' => 'items',
];
/**
* {@inheritdoc}
*/
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['prePubLogFilter'] = [
'class' => PrePubLogFilter::className(),
'only' => ['standard-create', 'video-create', 'images-create'],
];
return $behaviors;
}
/**
* @inheritdoc
*/
public function actions()
{
$actions = parent::actions();
// 禁用"create"、"update"、"delete"、"options"动作
unset($actions['create'], $actions['update'], $actions['delete'], $actions['options']);
$actions['index']['class'] = 'qq/rests/article/IndexAction';
$actions['view']['class'] = 'qq/rests/article/ViewAction';
$actions['standard-create'] = [
'class' => 'qq/rests/article/StandardCreateAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
$actions['video-create'] = [
'class' => 'qq/rests/article/VideoCreateAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
$actions['images-create'] = [
'class' => 'qq/rests/article/ImagesCreateAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
return $actions;
}
}

11、发布文章类型:标准(普通、图文)的文章,发布失败(即未入库,因为数据验证失败),此时,当返回码不等于 10000 时,插入 2 条记录(预发布日志),因为有 2 个帐号,查看 SQL

{
"code": 226004,
"message": "数据验证失败:标题只能包含至多255个字符。"
}
INSERT INTO `cpa_pre_pub_log` (`group_id`, `channel_id`, `channel_code`, `type`, `article_type_id`, `article_type_code`, `article_type_name`, `article_category_id`, `article_title`, `article_author`, `source`, `source_uuid`, `source_pub_user_id`, `source_callback_url`, `source_article_id`, `pub_log_code`, `pub_log_message`, `pub_log_body`, `status`, `is_deleted`, `created_at`, `updated_at`, `deleted_at`, `uuid`, `channel_type_id`, `channel_type_code`, `channel_app_source_id`, `channel_app_source_uuid`) VALUES ('015ce30b116ce86058fa6ab4fea4ac63', 1, 'qq', 'pub', 1, 'standard', '标准(普通)', 15, '未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化。北京时间 2019 年 12 月 28 日,1999-2019“星光中国芯工程”创新成果与展望报告会在人民大会堂举行。会议回顾和总结了“星光中国芯工程”20 年来在核心技术自主创新、在研发成果大规模产业化、以及在满足国家重大工程技术需求方面取得的重要进展和成功经验,并对“星光中国芯工程”未来发展进行了规划和展望。中国工程院院士、“星光中国芯工程”总指挥、中星微电子集团创建人兼首席科学家邓中翰作了“星光中国芯工程”20 年成果与展望工作报告,报告中,邓中翰表示,在物理层面智能芯片的发展已经受到了物理规律的限制,看似已经接近了极限的时候,在信息层面的技术创新还远远没有碰到天花板。1999 年,邓中翰等一批海外爱国博士企业家回国承担并启动实施“星光中国芯工程”,在北京中关村设立中星微电子公司,致力于超大规模集成电路芯片的研发、设计及产业化工作。2001 年,中国第一颗百万门级超大规模数字多媒体芯片“星光一号”诞生。其后数年间,“星光多媒体”系列芯片被苹果、三星、飞利浦、惠普、LG、索尼、戴尔等国外知名品牌规模采用,占领了全球计算机图像输入芯片 60% 以上的市场份额,彻底结束了中国无“芯”的历史。', '高琳', 'spider', '825e6d5e36468cc4bf536799ce3565cf', 3, 'http://scms.wjdev.chinamcloud.cn/api/thirdPush/callBack', 1, 226004, '数据验证失败:标题只能包含至多255个字符。', 'a:17:{s:24:/"channel_app_source_uuids/";a:2:{i:0;s:32:/"8d72b7cc2ac911eab85a54ee75d2ebc1/";i:1;s:32:/"18cf06d22ac911eaa31854ee75d2ebc1/";}s:6:/"source/";s:6:/"spider/";s:11:/"source_uuid/";s:32:/"825e6d5e36468cc4bf536799ce3565cf/";s:18:/"source_pub_user_id/";i:3;s:19:/"source_callback_url/";s:55:/"http://scms.wjdev.chinamcloud.cn/api/thirdPush/callBack/";s:19:/"article_category_id/";i:15;s:5:/"title/";s:1525:/"未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化。北京时间 2019 年 12 月 28 日,1999-2019“星光中国芯工程”创新成果与展望报告会在人民大会堂举行。会议回顾和总结了“星光中国芯工程”20 年来在核心技术自主创新、在研发成果大规模产业化、以及在满足国家重大工程技术需求方面取得的重要进展和成功经验,并对“星光中国芯工程”未来发展进行了规划和展望。中国工程院院士、“星光中国芯工程”总指挥、中星微电子集团创建人兼首席科学家邓中翰作了“星光中国芯工程”20 年成果与展望工作报告,报告中,邓中翰表示,在物理层面智能芯片的发展已经受到了物理规律的限制,看似已经接近了极限的时候,在信息层面的技术创新还远远没有碰到天花板。1999 年,邓中翰等一批海外爱国博士企业家回国承担并启动实施“星光中国芯工程”,在北京中关村设立中星微电子公司,致力于超大规模集成电路芯片的研发、设计及产业化工作。2001 年,中国第一颗百万门级超大规模数字多媒体芯片“星光一号”诞生。其后数年间,“星光多媒体”系列芯片被苹果、三星、飞利浦、惠普、LG、索尼、戴尔等国外知名品牌规模采用,占领了全球计算机图像输入芯片 60% 以上的市场份额,彻底结束了中国无“芯”的历史。/";s:6:/"author/";s:6:/"高琳/";s:17:/"source_article_id/";i:1;s:7:/"content/";s:1525:/"未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化。北京时间 2019 年 12 月 28 日,1999-2019“星光中国芯工程”创新成果与展望报告会在人民大会堂举行。会议回顾和总结了“星光中国芯工程”20 年来在核心技术自主创新、在研发成果大规模产业化、以及在满足国家重大工程技术需求方面取得的重要进展和成功经验,并对“星光中国芯工程”未来发展进行了规划和展望。中国工程院院士、“星光中国芯工程”总指挥、中星微电子集团创建人兼首席科学家邓中翰作了“星光中国芯工程”20 年成果与展望工作报告,报告中,邓中翰表示,在物理层面智能芯片的发展已经受到了物理规律的限制,看似已经接近了极限的时候,在信息层面的技术创新还远远没有碰到天花板。1999 年,邓中翰等一批海外爱国博士企业家回国承担并启动实施“星光中国芯工程”,在北京中关村设立中星微电子公司,致力于超大规模集成电路芯片的研发、设计及产业化工作。2001 年,中国第一颗百万门级超大规模数字多媒体芯片“星光一号”诞生。其后数年间,“星光多媒体”系列芯片被苹果、三星、飞利浦、惠普、LG、索尼、戴尔等国外知名品牌规模采用,占领了全球计算机图像输入芯片 60% 以上的市场份额,彻底结束了中国无“芯”的历史。/";s:10:/"cover_pics/";a:1:{i:0;s:84:/"https://static001.infoq.cn/resource/image/7c/18/7c55c468adf1d616f48681c23e9b9518.png/";}s:10:/"cover_type/";i:1;s:3:/"tag/";s:62:/"百度,发布,推理引擎,Paddle Lite,华为,NPU,在线编译/";s:5:/"apply/";i:0;s:17:/"original_platform/";i:0;s:12:/"original_url/";s:0:/"/";s:15:/"original_author/";s:0:/"/";}', 3, 0, 1578361765, 1578361765, 0, 'effddba230ef11ea991a54ee75d2ebc1', 1, 'qq_cw', 14, '8d72b7cc2ac911eab85a54ee75d2ebc1'), ('015ce30b116ce86058fa6ab4fea4ac63', 1, 'qq', 'pub', 1, 'standard', '标准(普通)', 15, '未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化。北京时间 2019 年 12 月 28 日,1999-2019“星光中国芯工程”创新成果与展望报告会在人民大会堂举行。会议回顾和总结了“星光中国芯工程”20 年来在核心技术自主创新、在研发成果大规模产业化、以及在满足国家重大工程技术需求方面取得的重要进展和成功经验,并对“星光中国芯工程”未来发展进行了规划和展望。中国工程院院士、“星光中国芯工程”总指挥、中星微电子集团创建人兼首席科学家邓中翰作了“星光中国芯工程”20 年成果与展望工作报告,报告中,邓中翰表示,在物理层面智能芯片的发展已经受到了物理规律的限制,看似已经接近了极限的时候,在信息层面的技术创新还远远没有碰到天花板。1999 年,邓中翰等一批海外爱国博士企业家回国承担并启动实施“星光中国芯工程”,在北京中关村设立中星微电子公司,致力于超大规模集成电路芯片的研发、设计及产业化工作。2001 年,中国第一颗百万门级超大规模数字多媒体芯片“星光一号”诞生。其后数年间,“星光多媒体”系列芯片被苹果、三星、飞利浦、惠普、LG、索尼、戴尔等国外知名品牌规模采用,占领了全球计算机图像输入芯片 60% 以上的市场份额,彻底结束了中国无“芯”的历史。', '高琳', 'spider', '825e6d5e36468cc4bf536799ce3565cf', 3, 'http://scms.wjdev.chinamcloud.cn/api/thirdPush/callBack', 1, 226004, '数据验证失败:标题只能包含至多255个字符。', 'a:17:{s:24:/"channel_app_source_uuids/";a:2:{i:0;s:32:/"8d72b7cc2ac911eab85a54ee75d2ebc1/";i:1;s:32:/"18cf06d22ac911eaa31854ee75d2ebc1/";}s:6:/"source/";s:6:/"spider/";s:11:/"source_uuid/";s:32:/"825e6d5e36468cc4bf536799ce3565cf/";s:18:/"source_pub_user_id/";i:3;s:19:/"source_callback_url/";s:55:/"http://scms.wjdev.chinamcloud.cn/api/thirdPush/callBack/";s:19:/"article_category_id/";i:15;s:5:/"title/";s:1525:/"未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化。北京时间 2019 年 12 月 28 日,1999-2019“星光中国芯工程”创新成果与展望报告会在人民大会堂举行。会议回顾和总结了“星光中国芯工程”20 年来在核心技术自主创新、在研发成果大规模产业化、以及在满足国家重大工程技术需求方面取得的重要进展和成功经验,并对“星光中国芯工程”未来发展进行了规划和展望。中国工程院院士、“星光中国芯工程”总指挥、中星微电子集团创建人兼首席科学家邓中翰作了“星光中国芯工程”20 年成果与展望工作报告,报告中,邓中翰表示,在物理层面智能芯片的发展已经受到了物理规律的限制,看似已经接近了极限的时候,在信息层面的技术创新还远远没有碰到天花板。1999 年,邓中翰等一批海外爱国博士企业家回国承担并启动实施“星光中国芯工程”,在北京中关村设立中星微电子公司,致力于超大规模集成电路芯片的研发、设计及产业化工作。2001 年,中国第一颗百万门级超大规模数字多媒体芯片“星光一号”诞生。其后数年间,“星光多媒体”系列芯片被苹果、三星、飞利浦、惠普、LG、索尼、戴尔等国外知名品牌规模采用,占领了全球计算机图像输入芯片 60% 以上的市场份额,彻底结束了中国无“芯”的历史。/";s:6:/"author/";s:6:/"高琳/";s:17:/"source_article_id/";i:1;s:7:/"content/";s:1525:/"未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化。北京时间 2019 年 12 月 28 日,1999-2019“星光中国芯工程”创新成果与展望报告会在人民大会堂举行。会议回顾和总结了“星光中国芯工程”20 年来在核心技术自主创新、在研发成果大规模产业化、以及在满足国家重大工程技术需求方面取得的重要进展和成功经验,并对“星光中国芯工程”未来发展进行了规划和展望。中国工程院院士、“星光中国芯工程”总指挥、中星微电子集团创建人兼首席科学家邓中翰作了“星光中国芯工程”20 年成果与展望工作报告,报告中,邓中翰表示,在物理层面智能芯片的发展已经受到了物理规律的限制,看似已经接近了极限的时候,在信息层面的技术创新还远远没有碰到天花板。1999 年,邓中翰等一批海外爱国博士企业家回国承担并启动实施“星光中国芯工程”,在北京中关村设立中星微电子公司,致力于超大规模集成电路芯片的研发、设计及产业化工作。2001 年,中国第一颗百万门级超大规模数字多媒体芯片“星光一号”诞生。其后数年间,“星光多媒体”系列芯片被苹果、三星、飞利浦、惠普、LG、索尼、戴尔等国外知名品牌规模采用,占领了全球计算机图像输入芯片 60% 以上的市场份额,彻底结束了中国无“芯”的历史。/";s:10:/"cover_pics/";a:1:{i:0;s:84:/"https://static001.infoq.cn/resource/image/7c/18/7c55c468adf1d616f48681c23e9b9518.png/";}s:10:/"cover_type/";i:1;s:3:/"tag/";s:62:/"百度,发布,推理引擎,Paddle Lite,华为,NPU,在线编译/";s:5:/"apply/";i:0;s:17:/"original_platform/";i:0;s:12:/"original_url/";s:0:/"/";s:15:/"original_author/";s:0:/"/";}', 3, 0, 1578361765, 1578361765, 0, 'effe253a30ef11eaa2e454ee75d2ebc1', 1, 'qq_cw', 13, '18cf06d22ac911eaa31854ee75d2ebc1')

12、查看 预发布日志 表,存在 2 条记录,符合预期,如图8

查看 预发布日志 表,存在 2 条记录,符合预期

图8

13、获取企鹅号的应用的任务列表,调整查询规则,基于 UNION ALL 语法,合并 预发布日志 的结果到一个结果集中。编辑 qq/rests/qq_app_task/IndexAction.php

<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace qq/rests/qq_app_task;
use Yii;
use qq/models/ArticleType;
use qq/models/ChannelAppTask;
use qq/models/PrePubLog;
use qq/models/PubLog;
use qq/models/QqArticle;
use qq/models/QqCwApp;
use qq/models/QqCwAppTask;
use qq/models/QqTransaction;
use qq/models/Task;
use yii/data/ActiveDataProvider;
use yii/db/Expression;
use yii/db/Query;
use yii/base/InvalidConfigException;
use yii/web/UnprocessableEntityHttpException;
/**
* 获取企鹅号的应用的任务列表:/qq-app-tasks(qq-app-task/index)
*
* For more details and usage information on IndexAction, see the [guide article on rest controllers](guide:rest-controllers).
*
* @author Qiang Wang <shuijingwanwq@163.com>
* @since 1.0
*/
class IndexAction extends /yii/rest/IndexAction
{
public $dataFilter = [
'class' => 'yii/data/ActiveDataFilter',
'searchModel' => 'qq/models/QqAppTaskSearch',
'attributeMap' => [
'group_id' => '{{%task}}.[[group_id]]',
'channel_type_code' => '{{%channel_app_task}}.[[channel_type_code]]',
'source' => '{{%task}}.[source]',
'source_uuid' => '{{%task}}.[[source_uuid]]',
'source_pub_user_id' => '{{%task}}.[[source_pub_user_id]]',
'channel_app_source_uuid' => '{{%channel_app_task}}.[[channel_app_source_uuid]]',
'penguin_name' => '{{%qq_cw_app}}.[[penguin_name]]',
'status' => '{{%channel_app_task}}.[[status]]',
'article_type_code' => '{{%article_type}}.[code]',
'article_category_id' => '{{%qq_article}}.[[article_category_id]]',
'article_title' => '{{%qq_article}}.[[title]]',
'article_author' => '{{%qq_article}}.[[author]]',
'source_article_id' => '{{%qq_article}}.[[source_article_id]]',
'created_at' => '{{%channel_app_task}}.[[created_at]]',
],
];
public $prePubLogDataFilter = [
'class' => 'yii/data/ActiveDataFilter',
'searchModel' => 'qq/models/QqAppTaskSearch',
'attributeMap' => [
'group_id' => '{{%pre_pub_log}}.[[group_id]]',
'channel_type_code' => '{{%pre_pub_log}}.[[channel_type_code]]',
'source' => '{{%pre_pub_log}}.[source]',
'source_uuid' => '{{%pre_pub_log}}.[[source_uuid]]',
'source_pub_user_id' => '{{%pre_pub_log}}.[[source_pub_user_id]]',
'channel_app_source_uuid' => '{{%pre_pub_log}}.[[channel_app_source_uuid]]',
'penguin_name' => '{{%qq_cw_app}}.[[penguin_name]]',
'status' => '{{%pre_pub_log}}.[[status]]',
'article_type_code' => '{{%pre_pub_log}}.[[article_type_code]]',
'article_category_id' => '{{%pre_pub_log}}.[[article_category_id]]',
'article_title' => '{{%pre_pub_log}}.[[article_title]]',
'article_author' => '{{%pre_pub_log}}.[[article_author]]',
'source_article_id' => '{{%pre_pub_log}}.[[source_article_id]]',
'created_at' => '{{%pre_pub_log}}.[[created_at]]',
],
];
/**
* Prepares the data provider that should return the requested collection of the models.
* @return ActiveDataProvider
* @throws InvalidConfigException if the configuration is invalid.
* @throws UnprocessableEntityHttpException
*/
protected function prepareDataProvider()
{
$requestParams = Yii::$app->getRequest()->getBodyParams();
if (empty($requestParams)) {
$requestParams = Yii::$app->getRequest()->getQueryParams();
}
$filter = null;
if ($this->dataFilter !== null) {
$this->dataFilter = Yii::createObject($this->dataFilter);
if ($this->dataFilter->load($requestParams)) {
$filter = $this->dataFilter->build();
if ($filter === false) {
$firstError = '';
foreach ($this->dataFilter->getFirstErrors() as $message) {
$firstError = $message;
break;
}
throw new UnprocessableEntityHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '224003'), ['first_error' => $firstError])), 224003);
}
}
}
$prePubLogFilter = null;
if ($this->prePubLogDataFilter !== null) {
$this->prePubLogDataFilter = Yii::createObject($this->prePubLogDataFilter);
if ($this->prePubLogDataFilter->load($requestParams)) {
$prePubLogFilter = $this->prePubLogDataFilter->build();
if ($prePubLogFilter === false) {
$firstError = '';
foreach ($this->prePubLogDataFilter->getFirstErrors() as $message) {
$firstError = $message;
break;
}
throw new UnprocessableEntityHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '224003'), ['first_error' => $firstError])), 224003);
}
}
}
if ($this->prepareDataProvider !== null) {
return call_user_func($this->prepareDataProvider, $this, $filter);
}
/* @var $modelClass ChannelAppTask */
$modelClass = $this->modelClass;
$channelAppTaskQuery = $modelClass::find()
->select([
new Expression("'channel_app_task'" . " AS 'model'"),
ChannelAppTask::tableName() . '.id',
Task::tableName() . '.group_id',
ChannelAppTask::tableName() . '.uuid',
ChannelAppTask::tableName() . '.channel_id',
ChannelAppTask::tableName() . '.channel_code',
ChannelAppTask::tableName() . '.channel_type_id',
ChannelAppTask::tableName() . '.channel_type_code',
ChannelAppTask::tableName() . '.channel_app_source_id',
ChannelAppTask::tableName() . '.channel_app_source_uuid',
Task::tableName() . '.type',
'article_type_id' => ArticleType::tableName() . '.id',
'article_type_code' => ArticleType::tableName() . '.code',
'article_type_name' => ArticleType::tableName() . '.name',
QqArticle::tableName() . '.article_category_id',
'article_title' => QqArticle::tableName() . '.title',
'article_author' => QqArticle::tableName() . '.author',
Task::tableName() . '.source',
Task::tableName() . '.source_uuid',
Task::tableName() . '.source_pub_user_id',
Task::tableName() . '.source_callback_url',
QqArticle::tableName() . '.source_article_id',
'pub_log_code' => PubLog::tableName() . '.code',
'pub_log_message' => PubLog::tableName() . '.message',
ChannelAppTask::tableName() . '.status',
ChannelAppTask::tableName() . '.is_deleted',
ChannelAppTask::tableName() . '.created_at',
ChannelAppTask::tableName() . '.updated_at',
ChannelAppTask::tableName() . '.deleted_at',
ChannelAppTask::tableName() . '.task_id',
ChannelAppTask::tableName() . '.have_pub_number',
QqCwApp::tableName() . '.penguin_name',
QqTransaction::tableName() . '.article_url',
])
->joinWith(['task.qqArticle.articleType'], false)
->joinWith(['qqCwAppTask.qqCwApp'], false)
->joinWith(['qqCwAppTask'], false)
->leftJoin(QqTransaction::tableName(), QqCwAppTask::tableName() . '.[[id]] = ' . QqTransaction::tableName() . '.[[qq_app_task_id]] AND ' . QqTransaction::tableName() . '.[[type]] = /'' . QqTransaction::TYPE_ARTICLE . '/'')
->joinWith(['pubLog'], false)
->where([
ChannelAppTask::tableName() . '.is_deleted' => ChannelAppTask::IS_DELETED_NO,
Task::tableName() . '.is_deleted' => Task::IS_DELETED_NO,
QqArticle::tableName() . '.is_deleted' => QqArticle::IS_DELETED_NO,
ArticleType::tableName() . '.is_deleted' => ArticleType::IS_DELETED_NO,
QqCwAppTask::tableName() . '.is_deleted' => QqCwAppTask::IS_DELETED_NO,
QqCwApp::tableName() . '.is_deleted' => QqCwApp::IS_DELETED_NO,
]);
if (!empty($filter)) {
$channelAppTaskQuery->andFilterWhere($filter);
}
$prePubLogQuery = PrePubLog::find()
->select([
new Expression("'pre_pub_log'" . " AS 'model'"),
PrePubLog::tableName() . '.id',
PrePubLog::tableName() . '.group_id',
PrePubLog::tableName() . '.uuid',
PrePubLog::tableName() . '.channel_id',
PrePubLog::tableName() . '.channel_code',
PrePubLog::tableName() . '.channel_type_id',
PrePubLog::tableName() . '.channel_type_code',
PrePubLog::tableName() . '.channel_app_source_id',
PrePubLog::tableName() . '.channel_app_source_uuid',
PrePubLog::tableName() . '.type',
PrePubLog::tableName() . '.article_type_id',
PrePubLog::tableName() . '.article_type_code',
PrePubLog::tableName() . '.article_type_name',
PrePubLog::tableName() . '.article_category_id',
PrePubLog::tableName() . '.article_title',
PrePubLog::tableName() . '.article_author',
PrePubLog::tableName() . '.source',
PrePubLog::tableName() . '.source_uuid',
PrePubLog::tableName() . '.source_pub_user_id',
PrePubLog::tableName() . '.source_callback_url',
PrePubLog::tableName() . '.source_article_id',
PrePubLog::tableName() . '.pub_log_code',
PrePubLog::tableName() . '.pub_log_message',
PrePubLog::tableName() . '.status',
PrePubLog::tableName() . '.is_deleted',
PrePubLog::tableName() . '.created_at',
PrePubLog::tableName() . '.updated_at',
PrePubLog::tableName() . '.deleted_at',
new Expression(0 . " AS 'task_id'"),
new Expression(ChannelAppTask::HAVE_PUB_NUMBER_DEFAULT . " AS 'have_pub_number'"),
QqCwApp::tableName() . '.penguin_name',
new Expression("''" . " AS 'article_url'"),
])
->joinWith(['qqCwApp'], false)
->where([
PrePubLog::tableName() . '.is_deleted' => ChannelAppTask::IS_DELETED_NO,
QqCwApp::tableName() . '.is_deleted' => QqCwApp::IS_DELETED_NO,
]);
if (!empty($prePubLogFilter)) {
$prePubLogQuery->andFilterWhere($prePubLogFilter);
}
$query = (new Query())
->from(['model' => $channelAppTaskQuery->union($prePubLogQuery, true)])
->orderBy(['created_at' => SORT_DESC, 'id' => SORT_DESC]);
return Yii::createObject([
'class' => ActiveDataProvider::className(),
'query' => $query,
'pagination' => [
'params' => $requestParams,
],
'sort' => [
'params' => $requestParams,
],
]);
}
}

14、获取企鹅号的应用的任务列表,列表中存在 2 条记录,查看获取企鹅号的应用的任务列表的请求参数、响应参数、 SQL 语句,符合预期,如图9

获取企鹅号的应用的任务列表,列表中存在 2 条记录,查看获取企鹅号的应用的任务列表的请求参数、响应参数、 SQL 语句,符合预期

图9

group_id:015ce30b116ce86058fa6ab4fea4ac63
filter[group_id]:015ce30b116ce86058fa6ab4fea4ac63
filter[channel_type_code]:qq_cw
filter[penguin_name][like]:华栖云秀
{
"code": 10000,
"message": "获取企鹅号的应用的任务列表成功",
"data": {
"items": [
{
"model": "pre_pub_log",
"id": 4,
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"uuid": "effddba230ef11ea991a54ee75d2ebc1",
"channel_id": 1,
"channel_code": "qq",
"channel_type_id": 1,
"channel_type_code": "qq_cw",
"channel_app_source_id": 14,
"channel_app_source_uuid": "8d72b7cc2ac911eab85a54ee75d2ebc1",
"type": "pub",
"article_type_id": "1",
"article_type_code": "standard",
"article_type_name": "标准(普通)",
"article_category_id": 15,
"article_title": "未来 10 年,“星光中国芯工程”计划投资 100 亿元用于芯片研发及大规模产业化。北京时间 2019 年 12 月 28 日,1999-2019“星光中国芯工程”创新成果与展望报告会在人民大会堂举行。会议回顾和总结了“星光中国芯工程”20 年来在核心技术自主创新、在研发成果大规模产业化、以及在满足国家重大工程技术需求方面取得的重要进展和成功经验,并对“星光中国芯工程”未来发展进行了规划和展望。中国工程院院士、“星光中国芯工程”总指挥、中星微电子集团创建人兼首席科学家邓中翰作了“星光中国芯工程”20 年成果与展望工作报告,报告中,邓中翰表示,在物理层面智能芯片的发展已经受到了物理规律的限制,看似已经接近了极限的时候,在信息层面的技术创新还远远没有碰到天花板。1999 年,邓中翰等一批海外爱国博士企业家回国承担并启动实施“星光中国芯工程”,在北京中关村设立中星微电子公司,致力于超大规模集成电路芯片的研发、设计及产业化工作。2001 年,中国第一颗百万门级超大规模数字多媒体芯片“星光一号”诞生。其后数年间,“星光多媒体”系列芯片被苹果、三星、飞利浦、惠普、LG、索尼、戴尔等国外知名品牌规模采用,占领了全球计算机图像输入芯片 60% 以上的市场份额,彻底结束了中国无“芯”的历史。",
"article_author": "高琳",
"source": "spider",
"source_uuid": "825e6d5e36468cc4bf536799ce3565cf",
"source_pub_user_id": 3,
"source_callback_url": "http://scms.wjdev.chinamcloud.cn/api/thirdPush/callBack",
"source_article_id": 1,
"pub_log_code": "226004",
"pub_log_message": "数据验证失败:标题只能包含至多255个字符。",
"status": 3,
"is_deleted": 0,
"created_at": 1578361765,
"updated_at": 1578361765,
"deleted_at": 0,
"task_id": 0,
"have_pub_number": "3",
"penguin_name": "华栖云秀",
"article_url": ""
},
{
"model": "channel_app_task",
"id": 1,
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"uuid": "3a1d31262acc11ea9f5754ee75d2ebc1",
"channel_id": 1,
"channel_code": "qq",
"channel_type_id": 1,
"channel_type_code": "qq_cw",
"channel_app_source_id": 14,
"channel_app_source_uuid": "8d72b7cc2ac911eab85a54ee75d2ebc1",
"type": "pub",
"article_type_id": "1",
"article_type_code": "standard",
"article_type_name": "标准(普通)",
"article_category_id": 15,
"article_title": "2019 年 22 款最佳软件开发工具",
"article_author": "Guru99",
"source": "spider",
"source_uuid": "825e6d5e36468cc4bf536799ce3565cf",
"source_pub_user_id": 3,
"source_callback_url": "http://scms.wjdev.chinamcloud.cn/api/thirdPush/callBack",
"source_article_id": 1,
"pub_log_code": "",
"pub_log_message": "",
"status": 4,
"is_deleted": 0,
"created_at": 1577686722,
"updated_at": 1577690249,
"deleted_at": 0,
"task_id": 1,
"have_pub_number": "3",
"penguin_name": "华栖云秀",
"article_url": ""
}
],
"_links": {
"self": {
"href": "http://api.channel-pub-api.localhost/qq/v1/qq-app-tasks?group_id=015ce30b116ce86058fa6ab4fea4ac63&filter%5Bgroup_id%5D=015ce30b116ce86058fa6ab4fea4ac63&filter%5Bchannel_type_code%5D=qq_cw&filter%5Bpenguin_name%5D%5Blike%5D=%E5%8D%8E%E6%A0%96%E4%BA%91%E7%A7%80&page=1"
}
},
"_meta": {
"totalCount": 2,
"pageCount": 1,
"currentPage": 1,
"perPage": 20
}
}
}
SELECT * FROM ((SELECT 'channel_app_task' AS 'model', `cpa_channel_app_task`.`id`, `cpa_task`.`group_id`, `cpa_channel_app_task`.`uuid`, `cpa_channel_app_task`.`channel_id`, `cpa_channel_app_task`.`channel_code`, `cpa_channel_app_task`.`channel_type_id`, `cpa_channel_app_task`.`channel_type_code`, `cpa_channel_app_task`.`channel_app_source_id`, `cpa_channel_app_task`.`channel_app_source_uuid`, `cpa_task`.`type`, `cpa_article_type`.`id` AS `article_type_id`, `cpa_article_type`.`code` AS `article_type_code`, `cpa_article_type`.`name` AS `article_type_name`, `cpa_qq_article`.`article_category_id`, `cpa_qq_article`.`title` AS `article_title`, `cpa_qq_article`.`author` AS `article_author`, `cpa_task`.`source`, `cpa_task`.`source_uuid`, `cpa_task`.`source_pub_user_id`, `cpa_task`.`source_callback_url`, `cpa_qq_article`.`source_article_id`, `cpa_pub_log`.`code` AS `pub_log_code`, `cpa_pub_log`.`message` AS `pub_log_message`, `cpa_channel_app_task`.`status`, `cpa_channel_app_task`.`is_deleted`, `cpa_channel_app_task`.`created_at`, `cpa_channel_app_task`.`updated_at`, `cpa_channel_app_task`.`deleted_at`, `cpa_channel_app_task`.`task_id`, `cpa_channel_app_task`.`have_pub_number`, `cpa_qq_cw_app`.`penguin_name`, `cpa_qq_transaction`.`article_url` FROM `cpa_channel_app_task` LEFT JOIN `cpa_task` ON `cpa_channel_app_task`.`task_id` = `cpa_task`.`id` LEFT JOIN `cpa_qq_article` ON `cpa_task`.`id` = `cpa_qq_article`.`task_id` LEFT JOIN `cpa_article_type` ON `cpa_qq_article`.`article_type_id` = `cpa_article_type`.`id` LEFT JOIN `cpa_qq_cw_app_task` ON `cpa_channel_app_task`.`id` = `cpa_qq_cw_app_task`.`channel_app_task_id` LEFT JOIN `cpa_qq_cw_app` ON `cpa_qq_cw_app_task`.`qq_cw_app_id` = `cpa_qq_cw_app`.`id` LEFT JOIN `cpa_pub_log` ON `cpa_channel_app_task`.`id` = `cpa_pub_log`.`channel_app_task_id` LEFT JOIN `cpa_qq_transaction` ON `cpa_qq_cw_app_task`.`id` = `cpa_qq_transaction`.`qq_app_task_id` AND `cpa_qq_transaction`.`type` = '1' WHERE ((`cpa_channel_app_task`.`is_deleted`=0) AND (`cpa_task`.`is_deleted`=0) AND (`cpa_qq_article`.`is_deleted`=0) AND (`cpa_article_type`.`is_deleted`=0) AND (`cpa_qq_cw_app_task`.`is_deleted`=0) AND (`cpa_qq_cw_app`.`is_deleted`=0)) AND ((`cpa_task`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`cpa_channel_app_task`.`channel_type_code`='qq_cw') AND (`cpa_qq_cw_app`.`penguin_name` LIKE '%华栖云秀%'))) UNION ALL ( SELECT 'pre_pub_log' AS 'model', `cpa_pre_pub_log`.`id`, `cpa_pre_pub_log`.`group_id`, `cpa_pre_pub_log`.`uuid`, `cpa_pre_pub_log`.`channel_id`, `cpa_pre_pub_log`.`channel_code`, `cpa_pre_pub_log`.`channel_type_id`, `cpa_pre_pub_log`.`channel_type_code`, `cpa_pre_pub_log`.`channel_app_source_id`, `cpa_pre_pub_log`.`channel_app_source_uuid`, `cpa_pre_pub_log`.`type`, `cpa_pre_pub_log`.`article_type_id`, `cpa_pre_pub_log`.`article_type_code`, `cpa_pre_pub_log`.`article_type_name`, `cpa_pre_pub_log`.`article_category_id`, `cpa_pre_pub_log`.`article_title`, `cpa_pre_pub_log`.`article_author`, `cpa_pre_pub_log`.`source`, `cpa_pre_pub_log`.`source_uuid`, `cpa_pre_pub_log`.`source_pub_user_id`, `cpa_pre_pub_log`.`source_callback_url`, `cpa_pre_pub_log`.`source_article_id`, `cpa_pre_pub_log`.`pub_log_code`, `cpa_pre_pub_log`.`pub_log_message`, `cpa_pre_pub_log`.`status`, `cpa_pre_pub_log`.`is_deleted`, `cpa_pre_pub_log`.`created_at`, `cpa_pre_pub_log`.`updated_at`, `cpa_pre_pub_log`.`deleted_at`, 0 AS 'task_id', 3 AS 'have_pub_number', `cpa_qq_cw_app`.`penguin_name`, '' AS 'article_url' FROM `cpa_pre_pub_log` LEFT JOIN `cpa_qq_cw_app` ON `cpa_pre_pub_log`.`channel_app_source_id` = `cpa_qq_cw_app`.`channel_app_source_id` WHERE ((`cpa_pre_pub_log`.`is_deleted`=0) AND (`cpa_qq_cw_app`.`is_deleted`=0)) AND ((`cpa_pre_pub_log`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') AND (`cpa_pre_pub_log`.`channel_type_code`='qq_cw') AND (`cpa_qq_cw_app`.`penguin_name` LIKE '%华栖云秀%')) )) `model` ORDER BY `created_at` DESC, `id` DESC LIMIT 20

15、仍然存在问题,当响应状态码为 404、302 时,未执行到过滤器方法:afterAction($action, $result),预发布日志表中未插入记录,有待于后续进一步分析处理,如图10

仍然存在问题,当响应状态码为 404、302 时,未执行到过滤器方法:afterAction($action, $result),预发布日志表中未插入记录,有待于后续进一步分析处理

图10

{
"name": "Not Found",
"message": "渠道的应用的来源UUID:8d72b7cc2ac911eab85a54ee75d2ebc0,不存在",
"code": 202001,
"status": 404,
"type": "yii//web//NotFoundHttpException"
}
{
"name": "Found",
"message": "微博的微连接的网页应用的用户的访问令牌的渠道的应用的来源ID(UUID):bad753742ad511ea9d2054ee75d2ebc1,的访问令牌已失效",
"code": 202136,
"status": 302,
"type": "yii//web//HttpException"
}

原创文章,作者:kepupublish,如若转载,请注明出处:https://blog.ytso.com/181456.html

(0)
上一篇 2021年11月1日
下一篇 2021年11月1日

相关推荐

发表回复

登录后才能评论