diff --git a/composer.json b/composer.json
index 9c562a6..f5714d0 100644
--- a/composer.json
+++ b/composer.json
@@ -30,6 +30,9 @@
"autoload": {
"psr-4": {
"Dhd\\Micro\\Core\\": "src/"
- }
+ },
+ "files": [
+ "src/helpers.php"
+ ]
}
}
diff --git a/src/Library/LogHelper.php b/src/Library/LogHelper.php
new file mode 100644
index 0000000..1a0bb5e
--- /dev/null
+++ b/src/Library/LogHelper.php
@@ -0,0 +1,80 @@
+log($level, $message, $enrichedContext);
+ }
+
+ protected static function getLogger(string $channel = 'default'): LoggerInterface
+ {
+ $container = ApplicationContext::getContainer();
+ $loggerFactory = $container->get(LoggerFactory::class);
+ return $loggerFactory->get($channel);
+ }
+
+ protected static function getTraceContext(): array
+ {
+ $context = [];
+
+ try {
+ $container = ApplicationContext::getContainer();
+ $rpcContext = $container->get(RpcContext::class);
+
+ $traceId = $rpcContext->get('trace_id');
+ if ($traceId) {
+ $context['trace_id'] = $traceId;
+ }
+ } catch (Throwable $e) {
+ // 上下文不可用时静默降级
+ }
+
+ return $context;
+ }
+}
diff --git a/src/helpers.php b/src/helpers.php
new file mode 100644
index 0000000..d9f6051
--- /dev/null
+++ b/src/helpers.php
@@ -0,0 +1,157 @@
+get($name);
+ }
+}
+
+if (! function_exists('f_log')) {
+ /**
+ * 程序日志.
+ */
+ function f_log(string $msg, mixed $data)
+ {
+ $fatory = ApplicationContext::getContainer()->get(LoggerFactory::class);
+ $logger = $fatory->get('log', 'default');
+ $content = [
+ 'msg' => $msg,
+ 'data' => $data,
+ ];
+ $logger->info(json_encode($content, JSON_UNESCAPED_UNICODE));
+ }
+}
+
+if (! function_exists('f_debug')) {
+ /**
+ * debug日志.
+ */
+ function f_debug($msg)
+ {
+ $logger = ApplicationContext::getContainer()->get(StdoutLoggerInterface::class);
+ $logger->info((is_array($msg) || is_object($msg)) ? json_encode($msg, JSON_UNESCAPED_UNICODE) : $msg);
+ }
+}
+
+if (! function_exists('add_file_domain')) {
+ /**
+ * 为内容中的图片路径添加文件域名.
+ */
+ function add_file_domain($content, $simple = false, $fileDomain = null)
+ {
+ if (empty($content)) {
+ return $content;
+ }
+
+ $fileDomain = $fileDomain ?? get_file_domain() . '/';
+ if ($simple) {
+ if (is_string($content) && preg_match('#^(?:https?:)?//#i', $content)) {
+ return $content;
+ }
+ return $fileDomain . ltrim($content, '/');
+ }
+
+ $content = preg_replace_callback('/
]*src\s*=\s*["\'])([^"\']*)(["\'][^>]*)>/i', function ($matches) use ($fileDomain) {
+ $prefix = $matches[1];
+ $src = $matches[2];
+ $suffix = $matches[3];
+
+ if ($src === '' || preg_match('#^(?:https?:)?//#i', $src) || str_starts_with($src, 'data:')) {
+ return $matches[0];
+ }
+ $newSrc = rtrim($fileDomain, '/') . '/' . ltrim($src, '/');
+ return '
';
+ }, $content);
+
+ return $content;
+ }
+}
+
+if (! function_exists('remove_file_domain')) {
+ /**
+ * 移除内容中图片的文件域名.
+ */
+ function remove_file_domain($content, $fileDomain = null)
+ {
+ if (empty($content)) {
+ return $content;
+ }
+ $fileDomain = $fileDomain ?? get_file_domain();
+ $fileDomain = $fileDomain ? rtrim($fileDomain, '/') : '';
+ if ($fileDomain === '') {
+ return $content;
+ }
+ $pattern = '#' . preg_quote($fileDomain, '#') . '/+#';
+ return preg_replace($pattern, '', $content);
+ }
+}
+
+if (! function_exists('copy_file_safely')) {
+ /**
+ * 复制文件到指定路径,若目标目录不存在则递归创建.
+ */
+ function copy_file_safely($sourceFile, $destinationFile)
+ {
+ $safeLog = function ($msg, $data) {
+ try {
+ f_log($msg, $data);
+ } catch (Throwable $e) {
+ // 忽略日志错误
+ }
+ };
+
+ if (! file_exists($sourceFile)) {
+ $safeLog('源文件不存在', $sourceFile);
+ return false;
+ }
+
+ $destinationDir = dirname($destinationFile);
+ if (! is_dir($destinationDir)) {
+ if (! mkdir($destinationDir, 0755, true)) {
+ $safeLog('无法创建目标目录', $destinationDir);
+ return false;
+ }
+ }
+
+ if (! is_writable($destinationDir)) {
+ $safeLog('目标目录不可写', $destinationDir);
+ return false;
+ }
+
+ if (copy($sourceFile, $destinationFile)) {
+ return true;
+ }
+
+ $error = error_get_last();
+ $safeLog('文件复制失败', $error['message'] ?? '未知错误');
+ return false;
+ }
+}