| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- <?php
- namespace console\controllers;
- use bizGhs\order\models\Order as GhsOrder;
- use bizHd\purchase\models\Purchase;
- use common\components\stringUtil;
- use Yii;
- use yii\console\Controller;
- use yii\console\ExitCode;
- /**
- * 补充历史订单 salt 字段
- *
- * 用法:
- * php yii salt/fill
- * php yii salt/fill --dryRun=1
- * php yii salt/fill --batchSize=50 --sleepMs=200
- * php yii salt/fill-ghs-order
- * php yii salt/fill-cg
- */
- class SaltController extends Controller
- {
- /** @var int 每批处理条数 */
- public $batchSize = 100;
- /** @var int 每批之间的休眠毫秒数,降低白天执行时的数据库压力 */
- public $sleepMs = 100;
- /** @var int 最多处理条数,0 表示全部 */
- public $limit = 0;
- /** @var int 是否仅预览,1=是 */
- public $dryRun = 0;
- public function options($actionID)
- {
- return array_merge(parent::options($actionID), ['batchSize', 'sleepMs', 'limit', 'dryRun']);
- }
- /**
- * 补充 xhGhsOrder、xhCg 历史数据的 salt 字段
- */
- public function actionFill()
- {
- return $this->runFill([
- 'xhGhsOrder' => GhsOrder::tableName(),
- 'xhCg' => Purchase::tableName(),
- ]);
- }
- /**
- * 仅补充 xhGhsOrder
- */
- public function actionFillGhsOrder()
- {
- return $this->runFill([
- 'xhGhsOrder' => GhsOrder::tableName(),
- ]);
- }
- /**
- * 仅补充 xhCg
- */
- public function actionFillCg()
- {
- return $this->runFill([
- 'xhCg' => Purchase::tableName(),
- ]);
- }
- private function runFill(array $tables)
- {
- ini_set('memory_limit', '512M');
- set_time_limit(0);
- if ($this->batchSize < 1) {
- $this->stderr("batchSize 必须大于 0\n");
- return ExitCode::UNSPECIFIED_ERROR;
- }
- $exitCode = ExitCode::OK;
- foreach ($tables as $label => $tableName) {
- $code = $this->fillTable($label, $tableName);
- if ($code !== ExitCode::OK) {
- $exitCode = $code;
- }
- }
- return $exitCode;
- }
- private function fillTable($label, $tableName)
- {
- $db = Yii::$app->db;
- $remaining = (int)$db->createCommand(
- "SELECT COUNT(*) FROM {$tableName} WHERE salt = ''"
- )->queryScalar();
- $this->stdout("{$label}({$tableName}) 待补充: {$remaining}\n");
- if ($remaining === 0) {
- return ExitCode::OK;
- }
- $processed = 0;
- $maxProcess = $this->limit > 0 ? min($this->limit, $remaining) : $remaining;
- $lastId = 0;
- while ($processed < $maxProcess) {
- $batchLimit = min($this->batchSize, $maxProcess - $processed);
- $rows = $db->createCommand(
- "SELECT id FROM {$tableName} WHERE salt = '' AND id > :lastId ORDER BY id ASC LIMIT {$batchLimit}"
- )->bindValue(':lastId', $lastId)->queryColumn();
- if (empty($rows)) {
- break;
- }
- foreach ($rows as $id) {
- $id = (int)$id;
- $lastId = $id;
- if ($this->dryRun) {
- $this->stdout("[dry-run] {$label} id={$id}\n");
- $processed++;
- continue;
- }
- $salt = stringUtil::charsShuffleLowerCase(10);
- $affected = $db->createCommand(
- "UPDATE {$tableName} SET salt = :salt WHERE id = :id AND salt = ''"
- )->bindValues([
- ':salt' => $salt,
- ':id' => $id,
- ])->execute();
- if ($affected > 0) {
- $processed++;
- }
- }
- $this->stdout("{$label} 已处理 {$processed}/{$maxProcess}\n");
- if ($this->sleepMs > 0 && $processed < $maxProcess) {
- usleep($this->sleepMs * 1000);
- }
- }
- $left = (int)$db->createCommand(
- "SELECT COUNT(*) FROM {$tableName} WHERE salt = ''"
- )->queryScalar();
- $this->stdout("{$label} 完成,本次处理 {$processed} 条,剩余 {$left} 条\n");
- return ExitCode::OK;
- }
- }
|