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