setName('admin:migrate:file:data') ->addOption('exec', null, Option::VALUE_NONE, '确认执行') ->setDescription('将数据库中的文件地址从老地址更新到新地址,只处理数据库数据,不会实际迁移文件'); } protected function execute(Input $input, Output $output) { if (empty($this->toDomain)) { $output->error('请指定新的文件域名'); return; } $this->fromDomain = array_filter($this->fromDomain, function ($domain) { return !empty($domain); }); if (empty($this->fromDomain)) { $output->error('请指定老的域名'); return; } // 指令输出 $model_files = []; foreach ($this->modelPath as $model_path) { $model_files = array_merge($model_files, glob($model_path . '/*.php')); } $model_class = []; foreach ($model_files as $file) { $class_name = str_replace('.php', '', $file); $class_name = str_replace('/', '\\', $class_name); $model_class[] = $class_name; } $field_map = []; foreach ($model_class as $class_name) { if (!isset($field_map[$class_name])) { $field_map[$class_name] = []; } $field_list_file = $class_name::FIELD_LIST_FILE; if (!empty($field_list_file)) { $field_map[$class_name] = array_merge($field_map[$class_name], $field_list_file); } $field_list_content = $class_name::FIELD_LIST_CONTENT; if (!empty($field_list_content)) { $field_map[$class_name] = array_merge($field_map[$class_name], $field_list_content); } } $from_domain_list = $this->getFromDomainList(); $to_domain = $this->toDomain; $exec = $input->hasOption('exec'); if(!$exec) { $output->writeln("输出模式,生成即将使用的sql,但不执行。"); $output->writeln("需要确认执行: php think admin:migrate:file:data --exec"); } $field_map = array_filter($field_map); foreach ($field_map as $model_class => $field_list) { $output->writeln("# process model {$model_class}"); foreach ($field_list as $field_name) { $output->writeln("# update field: {$field_name}"); foreach ($from_domain_list as $domain) { $result = $model_class::whereLike($field_name, "%$domain%") ->fetchSql(!$exec) ->update([ $field_name => Db::raw("REPLACE({$field_name}, '{$domain}', '{$to_domain}')"), ]); if($exec){ $output->writeln("exec affect rows: $result"); }else{ $output->writeln($result); } } } } } private function getFromDomainList() { $from_domain_list = []; foreach ($this->fromDomain as $from_domain) { if (!str_starts_with($from_domain, 'http://') && !str_starts_with($from_domain, 'https://')) { $from_domain_list[] = 'http://' . $from_domain; $from_domain_list[] = 'https://' . $from_domain; } else { $from_domain_list[] = $from_domain; } } return $from_domain_list; } }