我的烦恼你来解决 2025-08-12 15:48 采纳率: 71.4%
浏览 4
已结题

PHP-FPM转成swoole问题

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

img

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

如何解决
swoole代码

<?php
use think\App;
use think\Cache;
use think\Request;
use think\Log;
use think\Exception;
use think\response\Redirect as RedirectResponse;

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 = 80;      //监听端口号

    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){
                $_GET = [];
                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';   // 保持框架路由标识

                $_COOKIE = [];
                if (isset($request->cookie)) {
                    foreach ($request->cookie as $k => $v) {
                        $_COOKIE[$k] = $v;
                    }
                }
                
                $param=array_merge($_GET,$_POST);
                Request::create($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD'],$param, $_COOKIE,$_FILES, $_SERVER);
                // 运行应用
//                ob_start();
                try {
                    $thinkresponse =App::run();
                    ob_start();
                    $thinkresponse->send();
                    $result = ob_get_clean();
                    $headers =$thinkresponse->getHeader();
                    $code =$thinkresponse->getCode();

                    // 手动发送响应到Swoole
                    foreach ($headers as$name => $value) {
                        if (is_null($value)) {
                            $response-> header($name);
                        } else {
                            $response-> header($name,$value);
                        }
                    }
                    $response->status($code);
                    $response->end($result);
                } catch ( \Exception $e) {
                    $response->status(500);
                    $response->end('Internal Server Error: ' . $e->getMessage());
                    return;
                }
            });
        });

        // 启动服务
        $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();
  • 写回答

5条回答 默认 最新

  • 我的烦恼你来解决 2025-08-26 09:24
    关注

    根据写日志追踪发现第一次登录
    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",现在明白是因为swoole是常驻内存

    img


    解决办法二:

    img

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

报告相同问题?

问题事件

  • 系统已结题 9月3日
  • 已采纳回答 8月26日
  • 创建了问题 8月12日