自制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

