You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自制PHP Router导致多级路由页面无法加载CSS的问题求助

问题描述

我从零实现了一个简单的Router,代码如下:

class Router {
    private static array $routes;

    public static function register($route = '/', $filename=''){
        self::$routes[$route] = $filename;
    }

    public static function run(string $URI){
        $route = explode('?', $URI)[0];
        $play = self::$routes[$route];

        if($play){
            try{
                var_dump($play);
                require_once $play;
            } catch(Error $e){
                echo "<h1>Can't find the file </h1> <p>" . $e -> getMessage() . "</p>";
            }
            
        }else{
            echo "<h1>Page not found 404</h1>";
        }
    }
}

主页面index.php通过引入外部的header和footer文件实现布局,中间调用Router加载对应页面,逻辑如下:

require_once dirname(__DIR__) . '/config/Router.php';
/**
 * Registration of routers =======================+
 */
Router::register('/', './index.php');
Router::register('/associations', dirname(__DIR__) . '/views/associations/index.php');
Router::register('/associations/add', dirname(__DIR__) . '/views/associations/add.php');
Router::register('/partnerships', dirname(__DIR__) . '/views/partnerships/index.php');
Router::register('/test/t', dirname(__DIR__) . '/views/associations/test.php');
/**
 * Definitions of variables ======================+
 */
$title = 'List of associations';
$page_title = 'Organize your partnerships in ***';
/**
 * Requiring the header for every page ===========+
 */
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '/views/layouts/header.php';
/**
 * 
 */
var_dump($_SERVER['REQUEST_URI']);
Router::run($_SERVER['REQUEST_URI']);

/**
 * Requiring the header for every page ===========+
 */
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'views/layouts/footer.php';

单级路由(如/)的页面能正常加载且CSS生效,但多级路由(如/associations/add)的页面能正常加载却无法读取CSS。注意:我未使用Composer,也未实现自动加载器!尝试修改CSS文件路径,但会影响其他使用同一header的页面,确认问题出在路由上,请问该如何解决?

解决方案

这个问题的核心是相对路径解析逻辑冲突:浏览器会把当前路由的URL路径当作资源请求的基准路径,比如访问/associations/add时,会把/associations/当作基准去请求CSS,导致路径错误(比如原本的css/style.css会被解析成/associations/css/style.css)。

以下是几种无需修改Router核心逻辑的解决方法:

1. 使用网站根绝对路径(推荐)

在header里引入CSS时,直接用根目录开头的绝对路径,确保浏览器始终从网站根目录寻找资源:

<!-- 假设CSS放在项目根目录的css文件夹下 -->
<link rel="stylesheet" href="/css/style.css">

如果项目部署在网站子目录(比如http://example.com/my-project/),可以先定义根路径常量,再动态引入:

// 在index.php或全局配置文件中定义
define('BASE_URL', '/my-project/');

然后在header里使用:

<link rel="stylesheet" href="<?php echo BASE_URL; ?>css/style.css">

2. 设置HTML<base>标签

在header的<head>区域添加<base>标签,指定所有相对路径的基准URL:

<base href="/">

这样无论当前路由是几级,所有相对路径的资源请求都会以/为基准解析,和方法1效果一致。注意:该标签会影响页面内的锚点链接(如#top),需确保锚点路径匹配基准规则。

3. 动态生成相对路径(不推荐)

通过当前请求URI计算层级,动态生成向上跳转的相对路径:

// 计算当前路由的层级,比如/associations/add对应2级,需要../..
$uriSegments = explode('/', trim($_SERVER['REQUEST_URI'], '/'));
$level = count($uriSegments);
$basePath = $level > 0 ? str_repeat('../', $level) : '';

然后在header里引入CSS:

<link rel="stylesheet" href="<?php echo $basePath; ?>css/style.css">

这种方法需要处理单级路由等边界情况,维护成本较高,仅作为备选方案。

内容的提问来源于stack exchange,提问作者Zakaria DOUIH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 10:12:04