我的烦恼你来解决 2025-05-12 15:27 采纳率: 71.4%
浏览 35
已结题

把fastadmin的PHP-FPM转成swoole的http请求,刷新之后有些样式消失了变成这样l如何解决

把fastadmin的PHP-FPM转成swoole的http请求,但是登录成功后,首页正常,刷新之后有些样式消失了变成这样l

img


没有刷新之前的首页是

img


刷新之后的首页html

img


刷新之后,以

img


但是为什么第一次又能够加载呢?
swoole 刷新之后的请求

img

查看了首次登录的首页和刷新之后模版文件
首次登录模版代码

<?php if (!defined('THINK_PATH')) exit(); /*a:10:{s:69:"/var/www/html/server/../application/common/view/tpl/dispatch_jump.tpl";i:1736236336;s:66:"/var/www/html/server/../application/firmiana/view/index/login.html";i:1736236337;s:70:"/var/www/html/server/../application/firmiana/view/dashboard/index.html";i:1741931344;s:66:"/var/www/html/server/../application/firmiana/view/index/index.html";i:1736236337;s:59:"/var/www/html/application/firmiana/view/layout/default.html";i:1736236337;s:56:"/var/www/html/application/firmiana/view/common/meta.html";i:1736236337;s:58:"/var/www/html/application/firmiana/view/common/header.html";i:1751009709;s:56:"/var/www/html/application/firmiana/view/common/menu.html";i:1736236337;s:59:"/var/www/html/application/firmiana/view/common/control.html";i:1736236337;s:58:"/var/www/html/application/firmiana/view/common/script.html";i:1736236337;}*/ ?>

刷新之后的模版代码

<?php if (!defined('THINK_PATH')) exit(); /*a:6:{s:66:"/var/www/html/server/../application/firmiana/view/index/index.html";i:1736236337;s:56:"/var/www/html/application/firmiana/view/common/meta.html";i:1736236337;s:58:"/var/www/html/application/firmiana/view/common/header.html";i:1751009709;s:56:"/var/www/html/application/firmiana/view/common/menu.html";i:1736236337;s:59:"/var/www/html/application/firmiana/view/common/control.html";i:1736236337;s:58:"/var/www/html/application/firmiana/view/common/script.html";i:1736236337;}*/ ?>

img

在swoole的http请求 fastadmin 刷新之后的以layout的默认default.html文件为主,再加载index.html,而刚登录是以index.html为主,再加载默认default.html文件,如何在刷新时也以index.html为主,再加载默认default.html文件。

如何解决
swoole代码

<?php
use think\App;
use think\Request;
use think\Log;
class Http
{
    /**
     * Class Http  http服务器
     * 利用swoole提供的http服务器与thinkphp5.1框架及FastAdmin进行融合使用
     */
    /**
     * Swoole/Server 对象
     * @var \Swoole\Http\Server|null
     */
    protected $serv = null;

    /**
     * 监听IP
     * @var string
     */
    protected $host = '0.0.0.0';

    /**
     * 端口号
     * @var int
     */
    protected $port = 9501;      //监听端口号

    public function __construct()
    {
        $this->serv = new \Swoole\Http\Server($this->host, $this->port);

        $this->serv->set(array(
            'worker_num' => 1,
            'max_request' => 1000,
            'daemonize' => 0,
            'document_root' => __DIR__ . "/../public",
            'debug_mode' => 1,
            'buffer_output_size'=>32 * 1024 * 1024,
            'socket_buffer_size' => 32 * 1024 * 1024,
            "enable_static_handler" => true,
        ));

        //热更新
        $this->startFileWatcher();

        $this->serv->on('WorkerStart', function ($server, $worker_id) {
            // 定义应用路径
            define('APP_PATH', __DIR__ . '/../application/');
            // 加载thinkphp5.0 框架的基础文件
            require __DIR__ . '/../thinkphp/base.php';
        });

        // 监听服务器启动事件
        $this->serv->on('start', function ($server) {
            echo '服务器已启动,监听端口:' . $this->port . PHP_EOL;
        });


        $this->serv->on('request', function ($request, $response) {
            go(function () use ($request, $response){
                Log::write('Http server:'.json_encode($request->server),'App');
                // 处理静态文件请求
                $uri = $request->server['request_uri'];
               if (preg_match('/\.(css|js|png|jpg|jpeg|gif|ico|woff|woff2|ttf|svg)$/', $uri)) {
                   $file = __DIR__ . '/../public' . $uri;
                   if (file_exists($file)) {

                       if(!is_readable($file)){
                           Log::write('File is not readable: ' . $file, 'App');
                           $response->status(403);
                           $response->end('Forbidden');
                           return;
                       }
                       $response->header('Content-Type', $this->getMimeType($file));
                       // 尝试使用sendfile
                       if ($response->sendfile($file) === false) {
                           // 如果失败,改用分块读取发送
                           $fp = fopen($file, 'r');
                           if ($fp) {
                               while (!feof($fp)) {
                                   $chunk = fread($fp, 8192);
                                   $response->write($chunk);
                               }
                               fclose($fp);
                           }
                           $response->end();
                       }
                       return;
                   } else {
                       Log::write('File exists: ' . $file, 'App');
                       $response->status(404);
                       $response->end('File not found');
                       return;
                   }
               }

               // 处理 favicon.ico
               if ($uri == '/favicon.ico') {
                   $response->status(404);
                   $response->end();
                   return;
               }
//                // 处理根路径重定向
//                if ($uri === '/') {
//                    $response->redirect('/index/login', 302);
//                    return;
//                }

                // 初始化全局变量
                $_GET = ['s'=> parse_url($uri, PHP_URL_PATH)];
                if (isset($request->get)) {
                    foreach ($request->get as $k => $v) {
                        $_GET[$k] = $v;
                    }
                }
                $_POST = [];
                if (isset($request->post)) {
                    foreach ($request->post as $k => $v) {
                        $_POST[$k] = $v;
                    }
                }
                // 初始化文件上传变量
                $_FILES = [];
                if (isset($request->files)) {
                    foreach ($request->files as $k => $v) {
                        $_FILES[$k] = $v;
                    }
                }
                $_SERVER = [];
                $host = $request->header['host'];
                // 如果 Host 头不包含端口,手动添加
                if (strpos($host, ':') === false) {
                    $host .= ":$this->port"; // 或者动态获取 $this->port
                }
                if (isset($request->header)) {
                    foreach ($request->header as $k => $v) {
                        $_SERVER['HTTP_'.strtoupper(str_replace('-', '_', $k))] = $v;
                        if($k=='host'){
                            $_SERVER['HTTP_'.strtoupper(str_replace('-', '_', $k))]=$host;
                        }
                    }
                }
                if(isset($request->server)){
                    foreach ($request->server as $k => $v) {
                        $_SERVER[strtoupper($k)] = $v;
                    }
                }
                $_SERVER['SCRIPT_NAME'] = '/index.php';   // 保持框架路由标识
                $_SERVER['REQUEST_TIME_FLOAT'] = microtime(true); // Add this line
                Log::write('Http server:'.json_encode($_SERVER),'App');
                $_COOKIE = [];
                if (isset($request->cookie)) {
                    foreach ($request->cookie as $k => $v) {
                        $_COOKIE[$k] = $v;
                    }
                }

                $param=array_merge($_GET,$_POST);
                // 重新初始化 ThinkPHP 的请求对象 (关键步骤) 要不然POST请求都无法识别
                 Request::create($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD'],$param, $_COOKIE,$_FILES, $_SERVER);
                // 运行应用
                try {
                    $thinkResponse = App::run();
                } catch (\Exception $e) {
                    $response->status(500);
                    $response->end('Internal Server Error: ' . $e->getMessage());
                    return;
                }
                // 处理响应
                $response->status($thinkResponse->getCode());
                // 根据内容类型设置响应头
                foreach ($thinkResponse->getHeader() as $name => $value) {
                    $response->header($name, $value);
                }
                $response->end($thinkResponse->getContent());
            });
        });

        // 启动服务
        $this->serv->start();
    }

    /**
     * 获取文件的 MIME 类型
     * @param string $file 文件路径
     * @return string
     */
    private function getMimeType($file)
    {
        $mimeTypes = [
            'css'  => 'text/css',
            'js'   => 'application/javascript',
            'png'  => 'image/png',
            'jpg'  => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'gif'  => 'image/gif',
            'ico'  => 'image/x-icon',
            'woff' => 'font/woff',
            'woff2' => 'font/woff2',
            'ttf'  => 'font/ttf',
            'svg'  => 'image/svg+xml',
        ];

        $ext = pathinfo($file, PATHINFO_EXTENSION);
        return $mimeTypes[$ext] ?? 'text/plain';
    }

    /**
     * 启动文件监听器
     */
    private function startFileWatcher()
    {
        $watcher = new \Swoole\Process(function () {
            $paths = [
                __DIR__ . '/../application',
            ];

            $lastReloadTime = time();
            while (true) {
                foreach ($paths as $path) {
                    // Check if the directory exists before iterating
                    if (!is_dir($path)) {
                        continue;
                    }
                    /**
                     * RecursiveDirectoryIterator
                     * 这是一个用于遍历目录的迭代器,它可以递归地遍历目录及其子目录。
                     * 参数 $path 是要遍历的目录路径。
                     * 参数 \FilesystemIterator::SKIP_DOTS 是一个常量,用于告诉迭代器跳过 . 和 .. 目录(即当前目录和父目录)。
                     * RecursiveIteratorIterator:
                     * 这是一个迭代器迭代器,用于遍历嵌套的迭代器。
                     * 它接受一个 RecursiveDirectoryIterator 对象作为参数,并允许你递归地遍历目录结构
                     */
                    $iterator = new \RecursiveIteratorIterator(
                        new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS)
                    );
                    /**
                     * 遍历目录结构,并检查每个文件的最后修改时间是否大于 $lastReloadTime。
                     * 如果是,则重启 Worker 进程。
                     * 这样,当文件发生更改时,Worker 进程就会自动重启,从而使更改生效。
                     */
                    foreach ($iterator as $file) {
                        if ($file->getMTime() > $lastReloadTime) {
                            // 文件有更新,重启 Worker 进程
                            $this->serv->reload();
                            $lastReloadTime = time();
                            break 2;
                        }
                    }
                }
                sleep(1); // 每秒检查一次
            }
        });

        $watcher->start();
    }
}
//创建http服务器
$http = new Http();

  • 写回答

4条回答 默认 最新

  • 我的烦恼你来解决 2025-08-25 13:47
    关注

    根据写日志追踪发现第一次登录
    info
    [ 2025-08-25T11:37:11+08:00 ][ Controller config ] {"view_path":"/var/www/html/server/../application/firmiana/view/","view_base":"","view_suffix":"html","view_depr":"/","cache_suffix":"php","tpl_deny_func_list":"echo,exit","tpl_deny_php":false,"tpl_begin":"\{","tpl_end":"\}","strip_space":false,"tpl_cache":true,"compile_type":"file","cache_prefix":"","cache_time":0,"layout_on":false,"layout_name":"layout","layout_item":"{CONTENT}","taglib_begin":"\{","taglib_end":"\}","taglib_load":true,"taglib_build_in":"cx","taglib_pre_load":"","display_cache":false,"cache_id":"","tpl_replace_string":{"ROOT":"/","URL":"/firmiana/dashboard","STATIC":"/static","CSS":"/static/css","JS":"/static/js","PUBLIC":"/","CDN":""},"tpl_var_identify":"array","cache_path":"/var/www/html/runtime/temp/","auto_rule":1,"taglib_begin_origin":"{","taglib_end_origin":"}"}其中"layout_name":"layout"
    而刷新之后的
    info
    [ 2025-08-25T11:37:26+08:00 ][ Controller config ] {"view_path":"/var/www/html/server/../application/firmiana/view/","view_base":"","view_suffix":"html","view_depr":"/","cache_suffix":"php","tpl_deny_func_list":"echo,exit","tpl_deny_php":false,"tpl_begin":"\{","tpl_end":"\}","strip_space":false,"tpl_cache":true,"compile_type":"file","cache_prefix":"","cache_time":0,"layout_on":true,"layout_name":"layout/default","layout_item":"{CONTENT}","taglib_begin":"\{","taglib_end":"\}","taglib_load":true,"taglib_build_in":"cx","taglib_pre_load":"","display_cache":false,"cache_id":"","tpl_replace_string":{"ROOT":"/","URL":"/firmiana/dashboard","STATIC":"/static","CSS":"/static/css","JS":"/static/js","PUBLIC":"/","CDN":""},"tpl_var_identify":"array","cache_path":"/var/www/html/runtime/temp/","auto_rule":1,"taglib_begin_origin":"{","taglib_end_origin":"}"}其中"layout_name":"layout/default"

    img

    img


    info
    [ 2025-08-25T11:37:26+08:00 ][ Think config ] {"view_base":"","view_path":"/var/www/html/addons/epay/","view_suffix":"html","view_depr":"/","tpl_cache":true,"auto_rule":1,"tpl_begin":"{","tpl_end":"}","taglib_begin":"{","taglib_end":"}"}

    img

    但是不明白config中的layout_name为什么会变成"layout/default"

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 9月2日
  • 已采纳回答 8月25日
  • 修改了问题 8月11日
  • 修改了问题 7月9日
  • 展开全部