206 lines
6.7 KiB
PHP
206 lines
6.7 KiB
PHP
<?php
|
|
namespace core;
|
|
// 框架根目录
|
|
defined('CORE_PATH') or define('CORE_PATH', __DIR__);
|
|
|
|
/**
|
|
* fastphp 框架核心 - 最终修复版
|
|
*/
|
|
class Core
|
|
{
|
|
// 配置内容
|
|
protected $config = [];
|
|
|
|
public function __construct($config)
|
|
{
|
|
$this->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('<h2>控制器不存在:' . htmlspecialchars($controllerName) . '</h2>' .
|
|
'<p>访问的 URL: ' . htmlspecialchars($requestUri) . '</p>' .
|
|
'<p>解析后的路径:' . htmlspecialchars(implode('/', $urlArray ?? [])) . '</p>' .
|
|
'<p>请检查 URL 是否正确。</p>');
|
|
}
|
|
$this->notFound();
|
|
}
|
|
|
|
|
|
// 检查方法是否存在(如果控制器有 __call 魔术方法,允许动态方法通过)
|
|
if (!method_exists($controller, $actionName) && !method_exists($controller, '__call')) {
|
|
if (APP_DEBUG) {
|
|
exit('<h2>方法不存在:' . htmlspecialchars($actionName) . '</h2>' .
|
|
'<p>控制器:' . htmlspecialchars($controllerName) . 'Controller</p>' .
|
|
'<p>可用方法:<pre>' . htmlspecialchars(implode(', ', get_class_methods($controller))) . '</pre></p>');
|
|
}
|
|
$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',
|
|
];
|
|
}
|
|
}
|