造輪子不是為了替代成熟框架,而是為了在造輪子過程中深度理解框架內核:依賴注入、服務容器、中間件管道、事件系統等。本系列記錄從零構建「ZBS」微型框架的完過程,首篇確立入口文件、配置加載、PSR-4 自動加載、基礎路由分發四大核心骨架。
單入口模式:所有請求經 public/index.php → 定義常量/環境 → 加載配置/基礎類 → 路由解析 → 控制器分發 → 視圖渲染 → 響應輸出。每個環節都是擴展點。
<?php
// 1. 定義核心路徑常量
define('ROOT_PATH', __DIR__ . '/../');
define('APP_PATH', ROOT_PATH . 'app/');
define('SYS_PATH', ROOT_PATH . 'sys/');
define('CONF_PATH', APP_PATH . 'config/');
define('EXT', '.php');
// 2. 環境區分與錯誤級別
define('APP_ENV', getenv('APP_ENV') ?: 'development');
error_reporting(APP_ENV === 'production' ? E_ALL & ~E_NOTICE & ~E_DEPRECATED : E_ALL);
ini_set('display_errors', APP_ENV === 'development' ? '1' : '0');
// 3. 加載配置:返回數組的 PHP 文件
function compileConf($conf) {
foreach ($conf as $key => $val) {
is_array($val) ? compileConf($val) : define($key, $val);
}
}
compileConf(require_once CONF_PATH . 'config.php');
// 4. 註冊自動加載器並啟動路由
require_once SYS_PATH . 'Loader.php';
spl_autoload_register('Zbs\Loader::autoLoad');
\Zbs\Router::bootstrap();
<?php
return [
'URL_MODE' => 1, // 1: PATHINFO, 2: REWRITE
'DB_HOST' => '127.0.0.1',
'DB_NAME' => 'zbs',
'DB_USER' => 'root',
'DB_PWD' => '',
'DB_PREFIX' => 'zbs_',
'DEBUG' => true,
];
<?php
namespace Zbs;
class Loader {
public static function autoLoad($class) {
$class = ltrim($class, '\\');
$file = str_replace('\\', '/', $class) . EXT;
// 優先加載系統核心類
if (file_exists(SYS_PATH . $file)) {
include SYS_PATH . $file;
return;
}
// 再加載應用類
if (file_exists(APP_PATH . $file)) {
include APP_PATH . $file;
return;
}
// 可擴展:Vendor 目錄、Composer 映射等
}
}
設計要點: 命名空間與目錄結構一一對應 (Zbs\Controller\Index → sys/Controller/Index.php),spl_autoload_register 支援多加載器鏈,避免 __autoload 單一限制。
<?php
namespace Zbs;
class Router {
public static $uri;
public static function bootstrap() {
self::$uri = $_SERVER['REQUEST_URI'];
switch (URL_MODE) {
case 1: self::pathinfo(); break;
default: self::pathinfo();
}
}
protected static function pathinfo() {
// 解析 ?r=module/controller/action 兼容模式
$r = isset($_GET['r']) ? explode('/', trim($_GET['r'], '/')) : ['index', 'index'];
$controller = 'Controller\\' . ucfirst($r[0]);
$action = isset($r[1]) ? strtolower($r[1]) . 'Action' : 'indexAction';
if (!class_exists($controller)) {
throw new \Exception("Controller $controller not found", 404);
}
$instance = new $controller();
if (!method_exists($instance, $action)) {
throw new \Exception("Action $action not found", 404);
}
call_user_func([$instance, $action]);
}
}
訪問 index.php?r=index/login 即調用 app/Controller/Index.php::loginAction()。
zbs-framework/
├── public/ # Web 根目錄
│ └── index.php # 唯一入口
├── app/ # 應用層
│ ├── config/ # 配置文件
│ ├── Controller/ # 控制器
│ ├── Model/ # 模型
│ └── View/ # 視圖模板
├── sys/ # 系統核心
│ ├── Loader.php
│ ├── Router.php
│ ├── Controller.php (基類)
│ ├── Model.php (基類)
│ └── View.php (渲染引擎)
└── vendor/ # 第三方庫
view()、redirect()、json() 等常用響應方法。每一步都會參考 Laravel、ThinkPHP、Yii 等優秀框架的設計精華,並在博文中記錄關鍵決策與代碼實現。歡迎關注系列更新,一起在造輪子中精進 PHP 內功!
項目地址:GITHUB/zhenbianshu