理解框架核心運作原理,有助於深度使用現有框架或針對特殊需求自研輕量方案。
<?php
spl_autoload_register(function ($class) {
$baseDir = __DIR__ . '/src/';
$file = $baseDir . str_replace('\\', '/', $class) . '.php';
if (file_exists($file)) require $file;
});
// 命名空間對應目錄結構
// src/
// Controllers/
// Models/
// Views/
// Core/
// Helpers/
<?php
// public/index.php
require __DIR__ . '/../vendor/autoload.php';
$requestUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$path = trim($requestUri, '/');
$segments = $path ? explode('/', $path) : [];
// 預設值
$controllerName = $segments[0] ?? 'Home';
$actionName = $segments[1] ?? 'index';
$params = array_slice($segments, 2);
// 命名空間映射
$controllerClass = "App\\Controllers\\{$controllerName}Controller";
if (!class_exists($controllerClass)) {
http_response_code(404);
exit('Controller not found');
}
$controller = new $controllerClass();
$method = 'action' . ucfirst($actionName);
if (!method_exists($controller, $method)) {
http_response_code(404);
exit('Action not found');
}
// 反射自動綁定參數 (進階)
$refMethod = new ReflectionMethod($controller, $method);
$args = [];
foreach ($refMethod->getParameters() as $param) {
$name = $param->getName();
$args[] = $_GET[$name] ?? $_POST[$name] ?? ($param->isDefaultValueAvailable() ? $param->getDefaultValue() : null);
}
$response = $refMethod->invokeArgs($controller, $args);
// 統一回應輸出
if ($response instanceof Response) {
$response->send();
} elseif (is_string($response)) {
echo $response;
}
<?php
// Core/View.php
class View
{
private $file;
private $data = [];
public function __construct(string $file, array $data = [])
{
$this->file = $file;
$this->data = $data;
}
public function render(): string
{
// 擷取變數至區域作用域
extract($this->data, EXTR_SKIP);
// 開啟輸出緩衝捕獲內容
ob_start();
include $this->file;
return ob_get_clean();
}
// 魔術方法支援 $view->var 語法
public function __get($name) { return $this->data[$name] ?? null; }
public function __set($name, $value) { $this->data[$name] = $value; }
}
// Controller 使用
class PostController
{
public function actionView($id)
{
$post = Post::find($id);
$view = new View(__DIR__ . '/../Views/post/view.php', [
'post' => $post,
'title' => $post->title,
]);
return new HtmlResponse($view->render());
}
}
<?php
// 回應基類
abstract class Response
{
abstract public function send(): void;
}
// HTML 回應
class HtmlResponse extends Response
{
private $content;
public function __construct(string $content) { $this->content = $content; }
public function send() {
header('Content-Type: text/html; charset=UTF-8');
echo $this->content;
}
}
// JSON 回應
class JsonResponse extends Response
{
private $data;
public function __construct($data, int $status = 200) {
$this->data = $data;
http_response_code($status);
}
public function send() {
header('Content-Type: application/json; charset=UTF-8');
echo json_encode($this->data, JSON_UNESCAPED_UNICODE);
}
}
// 重導向回應
class RedirectResponse extends Response
{
private $url;
public function __construct(string $url, int $status = 302) {
$this->url = $url;
http_response_code($status);
}
public function send() {
header("Location: {$this->url}");
}
}
// Controller 回傳不同回應
class ApiController
{
public function actionList()
{
return new JsonResponse(['items' => Item::all()]);
}
public function actionCreate()
{
Item::create($_POST);
return new RedirectResponse('/items');
}
}
htmlspecialchars(),模板引擎自動轉義這個極簡架構雖不及成熟框架完善,但包含 MVC 核心精髓,擴充性強,適合學習或微型專案。