config = $config; } // 运行程序 public function run() { spl_autoload_register(array($this, 'loadClass')); $this->setReporting(); $this->removeMagicQuotes(); $this->unregisterGlobals(); $this->setDbConfig(); $this->route(); } // 路由处理 - 最终修复版 public function route() { $controllerName = 'Login'; $actionName = $this->config['defaultAction']; $param = array(); // 获取请求 URI $requestUri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/'; // 清除?之后的内容(查询字符串) $position = strpos($requestUri, '?'); if ($position !== false) { $requestUri = substr($requestUri, 0, $position); } // 解析 URL 路径 $url = trim($requestUri, '/'); if (!empty($url)) { // 分割 URL $urlArray = explode('/', $url); // 过滤:只移除空值和 index.php // 不再自动移除项目目录名,避免误判 $urlArray = array_values(array_filter($urlArray, function($value) { $lowerValue = strtolower($value); return $value !== '' && $lowerValue !== 'index.php'; })); // 现在 urlArray 应该是 [控制器,动作,参数...] if (!empty($urlArray)) { // 获取控制器名(首字母大写) $controllerName = ucfirst(strtolower($urlArray[0])); // 获取动作名 if (isset($urlArray[1]) && !empty($urlArray[1])) { $actionName = $urlArray[1]; } // 获取参数 if (isset($urlArray[2])) { $param = array_slice($urlArray, 2); } } } // 构建控制器类名 $controller = 'app\\controllers\\' . $controllerName . 'Controller'; // 检查控制器是否存在 if (!class_exists($controller)) { if (APP_DEBUG) { exit('
访问的 URL: ' . htmlspecialchars($requestUri) . '
' . '解析后的路径:' . htmlspecialchars(implode('/', $urlArray ?? [])) . '
' . '请检查 URL 是否正确。
'); } $this->notFound(); } // 检查方法是否存在(如果控制器有 __call 魔术方法,允许动态方法通过) if (!method_exists($controller, $actionName) && !method_exists($controller, '__call')) { if (APP_DEBUG) { exit('控制器:' . htmlspecialchars($controllerName) . 'Controller
' . '可用方法:
' . htmlspecialchars(implode(', ', get_class_methods($controller))) . '');
}
$this->notFound();
}
// 实例化控制器并调用方法
$dispatch = new $controller($controllerName, $actionName);
call_user_func_array(array($dispatch, $actionName), $param);
}
// 统一的 404 响应(生产环境不泄露任何细节)
protected function notFound()
{
if (!headers_sent()) {
header('HTTP/1.1 404 Not Found');
}
exit('404 Not Found');
}
// 检测开发环境
public function setReporting()
{
if (APP_DEBUG === true) {
error_reporting(E_ALL);
ini_set('display_errors','On');
} else {
error_reporting(E_ALL);
ini_set('display_errors','Off');
ini_set('log_errors', 'On');
// 自定义异常处理 — 防止敏感信息泄露
set_exception_handler(function($e) {
error_log('Unhandled exception: ' . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine());
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
exit('系统内部错误,请稍后重试');
});
}
}
// 删除敏感字符
public function stripSlashesDeep($value)
{
$value = is_array($value) ? array_map(array($this, 'stripSlashesDeep'), $value) : stripslashes($value);
return $value;
}
// 检测敏感字符并删除(已废弃)
public function removeMagicQuotes()
{
// 不再处理
}
// 检测自定义全局变量并移除
public function unregisterGlobals()
{
if (ini_get('register_globals')) {
$array = array('_SESSION', '_POST', '_GET', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES');
foreach ($array as $value) {
foreach ($GLOBALS[$value] as $key => $var) {
if ($var === $GLOBALS[$key]) {
unset($GLOBALS[$key]);
}
}
}
}
}
// 配置数据库信息
public function setDbConfig()
{
if ($this->config['db']) {
define('DB_HOST', $this->config['db']['host']);
define('DB_NAME', $this->config['db']['dbname']);
define('DB_USER', $this->config['db']['username']);
define('DB_PASS', $this->config['db']['password']);
}
}
// 自动加载类
public function loadClass($className)
{
$classMap = $this->classMap();
if (isset($classMap[$className])) {
$file = $classMap[$className];
} elseif (strpos($className, '\\') !== false) {
$file = APP_PATH . str_replace('\\', '/', $className) . '.php';
if (!is_file($file)) {
return;
}
} else {
return;
}
include $file;
}
// 内核文件命名空间映射关系
protected function classMap()
{
return [
'core\base\Controller' => CORE_PATH . '/base/Controller.php',
'core\base\Model' => CORE_PATH . '/base/Model.php',
'core\base\View' => CORE_PATH . '/base/View.php',
'core\db\Db' => CORE_PATH . '/db/Db.php',
'core\db\Sql' => CORE_PATH . '/db/Sql.php',
];
}
}