本文目录导读:

我来详细讲解如何在PHP中实现SPA(单页应用)。
SPA基础架构
前端路由处理
// index.php - 所有请求都进入这个文件
<?php
// 定义API路由
$routes = [
'/api/users' => 'UserController@index',
'/api/users/create' => 'UserController@create',
'/api/users/update' => 'UserController@update',
'/api/users/delete' => 'UserController@delete',
];
// 获取当前请求路径
$request_uri = $_SERVER['REQUEST_URI'];
$path = parse_url($request_uri, PHP_URL_PATH);
// API请求处理
if (strpos($path, '/api/') === 0) {
header('Content-Type: application/json');
// 路由分发逻辑
$response = handleApiRequest($path, $routes);
echo json_encode($response);
exit;
}
// 非API请求返回SPA主页面
include 'index.html';
RESTful API实现
简单的API控制器
class UserController {
public function index() {
// 获取用户列表
$users = [
['id' => 1, 'name' => 'John'],
['id' => 2, 'name' => 'Jane']
];
return ['status' => 'success', 'data' => $users];
}
public function create() {
// 创建用户
$data = json_decode(file_get_contents('php://input'), true);
// 处理逻辑
return ['status' => 'success', 'message' => 'User created'];
}
}
前端集成
创建SPA主页面
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>PHP SPA</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<nav>
<a href="#" @click.prevent="navigate('/')">Home</a>
<a href="#" @click.prevent="navigate('/users')">Users</a>
</nav>
<component :is="currentComponent"></component>
</div>
<script>
const { createApp } = Vue;
const app = createApp({
data() {
return {
currentRoute: '/',
currentComponent: 'home'
}
},
methods: {
navigate(path) {
this.currentRoute = path;
this.updateComponent();
// 更新URL而不刷新页面
history.pushState({}, '', path);
},
updateComponent() {
switch(this.currentRoute) {
case '/':
this.currentComponent = 'home';
break;
case '/users':
this.currentComponent = 'users';
break;
}
}
},
created() {
// 监听浏览器前进后退
window.addEventListener('popstate', () => {
this.currentRoute = window.location.pathname;
this.updateComponent();
});
}
});
// 定义组件
app.component('home', {
template: `<h1>Home Page</h1>`
});
app.component('users', {
template: `
<div>
<h1>Users List</h1>
<ul>
<li v-for="user in users">{{ user.name }}</li>
</ul>
<button @click="loadUsers">Load Users</button>
</div>
`,
data() {
return { users: [] }
},
methods: {
async loadUsers() {
const response = await fetch('/api/users');
const data = await response.json();
this.users = data.data;
}
}
});
app.mount('#app');
</script>
</body>
</html>
完整的API路由处理
<?php
// api.php - 更完善的API路由处理
class ApiRouter {
private $routes = [];
private $method;
private $path;
public function __construct() {
$this->method = $_SERVER['REQUEST_METHOD'];
$this->path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$this->setupRoutes();
}
private function setupRoutes() {
// 定义RESTful路由
$this->routes = [
'GET /api/users' => 'UserController@getUsers',
'GET /api/users/{id}' => 'UserController@getUser',
'POST /api/users' => 'UserController@createUser',
'PUT /api/users/{id}' => 'UserController@updateUser',
'DELETE /api/users/{id}' => 'UserController@deleteUser',
];
}
public function dispatch() {
$route = $this->method . ' ' . $this->path;
foreach ($this->routes as $pattern => $handler) {
$pattern = preg_replace('/\{[a-zA-Z]+\}/', '(\d+)', $pattern);
$pattern = str_replace('/', '\/', $pattern);
if (preg_match('/^' . $pattern . '$/', $route, $matches)) {
array_shift($matches);
list($controller, $method) = explode('@', $handler);
$instance = new $controller();
return call_user_func_array([$instance, $method], $matches);
}
}
// 404错误处理
http_response_code(404);
return ['error' => 'Route not found'];
}
}
// 用户控制器
class UserController {
private $users = [
1 => ['id' => 1, 'name' => 'John', 'email' => 'john@example.com'],
2 => ['id' => 2, 'name' => 'Jane', 'email' => 'jane@example.com']
];
public function getUsers() {
return ['status' => 'success', 'data' => array_values($this->users)];
}
public function getUser($id) {
if (isset($this->users[$id])) {
return ['status' => 'success', 'data' => $this->users[$id]];
}
return ['status' => 'error', 'message' => 'User not found'];
}
public function createUser() {
$data = json_decode(file_get_contents('php://input'), true);
$id = max(array_keys($this->users)) + 1;
$newUser = [
'id' => $id,
'name' => $data['name'] ?? '',
'email' => $data['email'] ?? ''
];
$this->users[$id] = $newUser;
return ['status' => 'success', 'data' => $newUser];
}
public function updateUser($id) {
$data = json_decode(file_get_contents('php://input'), true);
if (isset($this->users[$id])) {
$this->users[$id] = array_merge($this->users[$id], $data);
return ['status' => 'success', 'data' => $this->users[$id]];
}
return ['status' => 'error', 'message' => 'User not found'];
}
public function deleteUser($id) {
if (isset($this->users[$id])) {
unset($this->users[$id]);
return ['status' => 'success', 'message' => 'User deleted'];
}
return ['status' => 'error', 'message' => 'User not found'];
}
}
// 启动路由器
header('Content-Type: application/json');
$router = new ApiRouter();
$response = $router->dispatch();
echo json_encode($response);
使用框架(如Laravel)
如果你使用Laravel,SPA实现更简洁:
// routes/web.php
Route::get('/{any}', function () {
return view('app');
})->where('any', '.*');
// routes/api.php
Route::get('/users', 'UserController@index');
Route::post('/users', 'UserController@store');
CORS处理(跨域)
<?php
// 添加CORS头部
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
// 处理预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit();
}
安全考虑
<?php
// 输入验证和过滤
function sanitizeInput($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
// JWT认证示例
function verifyJWT($token) {
// 验证JWT token
// 返回用户信息或false
}
使用建议
- 适合场景:中小型项目、快速原型、需要PHP后端的项目
- 框架选择:Laravel、Symfony等成熟框架提供更好的SPA支持
- 前端技术:Vue.js、React、Angular等现代前端框架配合使用
- 性能优化:使用缓存、CDN分发静态资源、API响应压缩
这种架构的核心优势是前后端完全分离,API可复用,便于后期扩展和维护。