Pārlūkot izejas kodu

build(backend): 添加新闻扩展的 FFI 构建脚本

新增 `build.sh` 脚本用于编译 `lib_news.so` 并将其移动到 runtime 目录。
脚本会自动检测项目根目录、执行 make 命令并处理编译结果。

feat(backend): 调整新闻扩展 FFI 构建配置将 Go 版本从 1.24 降级至 1.18,以确保与 glibc2.32 兼容。
同时在 Makefile 中增加挂载本地 GOPATH 的配置。

refactor(backend): 更新新闻扩展 API 路由前缀

将新闻扩展的 API 路由前缀由 `/api/extension/news` 调整为 `/api/news`,简化路由结构,提升接口清晰度。fix(backend):优化 NewsFfiService 的库文件加载逻辑

调整 FFI 库文件加载路径判断逻辑,优先查找 runtime 目录下的
`lib_news.so`,若不存在则抛出明确异常提示。同时清理无用 try-catch
结构,使初始化流程更直观可靠。
runphp 6 mēneši atpakaļ
vecāks
revīzija
18618905b5
4 mainītis faili ar 76 papildinājumiem un 38 dzēšanām
  1. 3 1
      ffi/Makefile
  2. 39 0
      ffi/build.sh
  3. 9 9
      route/api.php
  4. 25 28
      src/Service/NewsFfiService.php

+ 3 - 1
ffi/Makefile

@@ -1,10 +1,12 @@
 # Makefile
 
 BINARY=lib_news.so
-GO_VERSION=1.24
+# 使用与glibc 2.32兼容的更低版本golang镜像
+GO_VERSION=1.18
 
 GO_BUILD=docker run --rm \
     -v $(PWD):/app \
+    -v $(HOME)/go:/go \
     -w /app \
     -e GOPROXY=https://goproxy.cn,direct \
     golang:$(GO_VERSION) \

+ 39 - 0
ffi/build.sh

@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# 获取脚本所在目录
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+# 获取项目根目录(当前目录的上三级目录,即backend目录)
+PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../../../" && pwd)"
+# 检查项目根目录是否存在
+if [ ! -d "$PROJECT_ROOT" ]; then
+    echo "Error: Project root directory not found"
+    exit 1
+fi
+echo "Project root directory: $PROJECT_ROOT"
+# 设置runtime目录路径为项目根目录下的runtime目录
+RUNTIME_DIR="$PROJECT_ROOT/runtime"
+# 进入脚本所在目录
+cd "$SCRIPT_DIR" || exit 1
+
+# 执行make命令
+echo "Building lib_news.so..."c
+make clean
+if ! make; then
+    echo "Error: Build failed"
+    exit 1
+fi
+
+# 检查编译结果是否存在
+if [ ! -f "lib_news.so" ]; then
+    echo "Error: lib_news.so not found after build"
+    exit 1
+fi
+
+# 创建runtime目录(如果不存在)
+mkdir -p "$RUNTIME_DIR"
+
+# 移动编译结果到runtime目录
+echo "Moving lib_news.so to runtime directory..."
+mv lib_news.so "$RUNTIME_DIR/"
+
+echo "Build completed successfully. lib_news.so moved to $RUNTIME_DIR/"

+ 9 - 9
route/api.php

@@ -6,12 +6,12 @@ use SixShop\News\Controller\Api\NewsController;
 use think\facade\Route;
 
 // 移动端/H5等 API 路由
-// 路由前缀: /api/extension/news
-Route::group('api/extension/news', function () {
-    // 分类API资源路由
-    Route::resource('category', CategoryController::class);
-    // 文章API资源路由
-    Route::resource('news', NewsController::class);
-    // 增加阅读数路由
-    Route::post('news/:id/views', [NewsController::class, 'incrementViews']);
-});
+// 路由前缀: /api/news
+
+// 分类API资源路由
+Route::resource('category', CategoryController::class);
+// 文章API资源路由
+Route::resource('news', NewsController::class);
+// 增加阅读数路由
+Route::post('news/:id/views', [NewsController::class, 'incrementViews']);
+

+ 25 - 28
src/Service/NewsFfiService.php

@@ -1,8 +1,9 @@
 <?php
+
 namespace SixShop\News\Service;
 
-use FFI;
 use Exception;
+use FFI;
 
 /**
  * FFI Service Wrapper for the News extension's Go library.
@@ -19,8 +20,8 @@ class NewsFfiService
      */
     private function __construct()
     {
-        try {
-            $cdef = "
+
+        $cdef = "
                 // Initialization function
                 char* Initialize(char* host, char* user, char* password, char* dbname, char* charset, int port);
 
@@ -40,36 +41,32 @@ class NewsFfiService
                 char* IncrementNewsViews(int id);
             ";
 
-            $libPath = __DIR__ . '/../../ffi/lib_news.so';
+        $libPath = __DIR__ . '/../../ffi/lib_news.so';
+        if (!file_exists($libPath)) {
+            $libPath = root_path('runtime') . 'lib_news.so';
             if (!file_exists($libPath)) {
                 throw new Exception("FFI library not found at: $libPath. Please run 'make' in the ffi directory.");
             }
+        }
 
-            $this->ffi = FFI::cdef($cdef, $libPath);
-
-            // Dynamically initialize the Go module with config from the environment
-            $dbConfig = config('database.connections.mysql');
-            
-            $resultJson = FFI::string($this->ffi->Initialize(
-                $dbConfig['hostname'],
-                $dbConfig['username'],
-                $dbConfig['password'],
-                $dbConfig['database'],
-                $dbConfig['charset'],
-                $dbConfig['hostport']
-            ));
-
-            $result = json_decode($resultJson, true);
-            if (!isset($result['status']) || $result['status'] !== 'ok') {
-                $error = $result['error'] ?? 'unknown initialization error';
-                throw new Exception("Failed to initialize Go FFI database: " . $error);
-            }
+        $this->ffi = FFI::cdef($cdef, $libPath);
+
+        // Dynamically initialize the Go module with config from the environment
+        $dbConfig = config('database.connections.mysql');
+
+        $resultJson = FFI::string($this->ffi->Initialize(
+            $dbConfig['hostname'],
+            $dbConfig['username'],
+            $dbConfig['password'],
+            $dbConfig['database'],
+            $dbConfig['charset'],
+            $dbConfig['hostport']
+        ));
 
-        } catch (Exception $e) {
-            // Handle FFI loading errors gracefully
-            // In a real application, you'd log this error.
-            // For now, we can re-throw it to make debugging easier.
-            throw new Exception("Failed to initialize News FFI Service: " . $e->getMessage());
+        $result = json_decode($resultJson, true);
+        if (!isset($result['status']) || $result['status'] !== 'ok') {
+            $error = $result['error'] ?? 'unknown initialization error';
+            throw new Exception("Failed to initialize Go FFI database: " . $error);
         }
     }