1. Web前后端数据交互基础概念
在Web开发中,前后端数据交互是构建动态网站的核心技术。PHP作为一种服务器端脚本语言,与前端JavaScript配合可以实现丰富的数据交互功能。典型的交互场景包括表单提交、AJAX请求、WebSocket通信等。
注意:现代Web开发中,前后端分离架构越来越流行,但理解传统PHP与前端直接交互的方式仍然是基础。
2. PHP处理表单数据的基本方法
2.1 GET与POST方法对比
PHP通过超全局变量$_GET和$_POST接收前端提交的数据:
php复制// GET方法示例
$username = $_GET['username'];
// POST方法示例
$password = $_POST['password'];
两种方法的区别:
- GET:数据附加在URL中,有长度限制,适合非敏感数据
- POST:数据在请求体中传输,更安全,适合表单提交
2.2 表单数据验证
接收用户输入必须进行验证:
php复制// 基础验证示例
if(empty($_POST['username'])){
die("用户名不能为空");
}
// 过滤特殊字符
$username = htmlspecialchars($_POST['username']);
3. AJAX与PHP交互实现
3.1 基础AJAX请求
前端JavaScript代码:
javascript复制// 使用原生JS发送AJAX请求
var xhr = new XMLHttpRequest();
xhr.open('POST', 'api.php', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
xhr.send('action=getData&id=123');
PHP端处理代码:
php复制// api.php
header('Content-Type: application/json');
$response = ['status' => 'success', 'data' => []];
if($_POST['action'] === 'getData') {
$id = intval($_POST['id']);
// 查询数据库等操作
$response['data'] = ['id' => $id, 'name' => '示例数据'];
}
echo json_encode($response);
3.2 使用Fetch API
现代浏览器推荐使用Fetch API:
javascript复制fetch('api.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({action: 'getData', id: 123})
})
.then(response => response.json())
.then(data => console.log(data));
PHP端需要相应调整:
php复制// 接收JSON格式数据
$input = json_decode(file_get_contents('php://input'), true);
4. 安全注意事项
4.1 防止SQL注入
必须使用预处理语句:
php复制// PDO预处理示例
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username");
$stmt->execute([':username' => $_POST['username']]);
4.2 CSRF防护
生成并验证CSRF令牌:
php复制// 生成令牌
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
// 验证令牌
if(!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
die('非法请求');
}
5. 文件上传处理
PHP处理文件上传:
php复制if($_FILES['file']['error'] === UPLOAD_ERR_OK) {
$tmpName = $_FILES['file']['tmp_name'];
$fileName = basename($_FILES['file']['name']);
$targetPath = "uploads/".$fileName;
// 检查文件类型
$fileType = strtolower(pathinfo($targetPath, PATHINFO_EXTENSION));
$allowed = ['jpg', 'png', 'pdf'];
if(in_array($fileType, $allowed)) {
move_uploaded_file($tmpName, $targetPath);
}
}
6. 会话管理与用户认证
6.1 基础会话管理
php复制// 启动会话
session_start();
// 设置会话变量
$_SESSION['user_id'] = 123;
// 销毁会话
session_destroy();
6.2 用户登录验证
php复制// 简单登录验证
if($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
// 实际项目中应该查询数据库验证
if($username === 'admin' && $password === '123456') {
$_SESSION['logged_in'] = true;
header('Location: dashboard.php');
exit;
}
}
7. RESTful API设计基础
7.1 基础API路由
php复制// 简单路由实现
$request = $_SERVER['REQUEST_URI'];
$method = $_SERVER['REQUEST_METHOD'];
switch($request) {
case '/api/users':
if($method === 'GET') {
// 获取用户列表
} elseif($method === 'POST') {
// 创建用户
}
break;
case preg_match('/\/api\/users\/(\d+)/', $request, $matches):
$userId = $matches[1];
if($method === 'GET') {
// 获取单个用户
}
break;
}
7.2 返回JSON响应
php复制header('Content-Type: application/json');
http_response_code(200);
echo json_encode([
'status' => 'success',
'data' => [
'id' => 1,
'name' => '示例用户'
]
]);
8. 常见问题与解决方案
8.1 跨域问题处理
在PHP端设置响应头:
php复制header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
header('Access-Control-Allow-Headers: Content-Type');
8.2 性能优化建议
- 使用OPcache加速PHP执行
- 合理设置会话存储方式
- 对频繁查询的数据使用缓存
8.3 调试技巧
开启错误报告:
php复制ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
检查请求数据:
php复制var_dump($_REQUEST);
file_put_contents('debug.log', print_r($_REQUEST, true), FILE_APPEND);
9. 实际项目中的应用示例
9.1 评论系统实现
前端HTML:
html复制<form id="commentForm">
<input type="text" name="name" placeholder="您的姓名">
<textarea name="content" placeholder="评论内容"></textarea>
<button type="submit">提交评论</button>
</form>
<div id="comments"></div>
JavaScript处理:
javascript复制document.getElementById('commentForm').addEventListener('submit', function(e) {
e.preventDefault();
fetch('comment.php', {
method: 'POST',
body: new FormData(this)
})
.then(response => response.json())
.then(data => {
if(data.success) {
loadComments();
}
});
});
function loadComments() {
fetch('comment.php?action=get')
.then(response => response.json())
.then(comments => {
let html = '';
comments.forEach(comment => {
html += `<div class="comment">
<h3>${comment.name}</h3>
<p>${comment.content}</p>
</div>`;
});
document.getElementById('comments').innerHTML = html;
});
}
PHP后端处理:
php复制// comment.php
session_start();
header('Content-Type: application/json');
if(!file_exists('comments.json')) {
file_put_contents('comments.json', '[]');
}
if($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = htmlspecialchars($_POST['name']);
$content = htmlspecialchars($_POST['content']);
$comments = json_decode(file_get_contents('comments.json'), true);
$comments[] = [
'name' => $name,
'content' => $content,
'time' => date('Y-m-d H:i:s')
];
file_put_contents('comments.json', json_encode($comments));
echo json_encode(['success' => true]);
} elseif(isset($_GET['action']) && $_GET['action'] === 'get') {
echo file_get_contents('comments.json');
}
10. 进阶话题与扩展学习
10.1 WebSocket实时通信
虽然PHP不是最适合WebSocket的语言,但可以通过Ratchet等库实现:
php复制// 使用Ratchet实现简单WebSocket服务器
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat implements MessageComponentInterface {
public function onOpen(ConnectionInterface $conn) {}
public function onClose(ConnectionInterface $conn) {}
public function onError(ConnectionInterface $conn, \Exception $e) {}
public function onMessage(ConnectionInterface $from, $msg) {}
}
$app = new Ratchet\App('localhost', 8080);
$app->route('/chat', new Chat);
$app->run();
10.2 使用Composer管理依赖
现代PHP项目推荐使用Composer:
bash复制# 安装Composer
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"
# 使用Composer安装包
php composer.phar require monolog/monolog
10.3 框架选择建议
根据项目规模选择合适的PHP框架:
- 小型项目:Slim、Lumen
- 中型项目:Laravel、Symfony
- 大型企业应用:Zend Framework
11. 性能监控与优化
11.1 基础性能分析
使用XHProf进行性能分析:
php复制// 开始分析
xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
// 你的代码...
// 结束分析
$xhprof_data = xhprof_disable();
include_once "xhprof_lib/utils/xhprof_lib.php";
include_once "xhprof_lib/utils/xhprof_runs.php";
$xhprof_runs = new XHProfRuns_Default();
$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_testing");
11.2 数据库查询优化
记录慢查询:
php复制// 在MySQL配置中设置
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1
使用EXPLAIN分析查询:
php复制$stmt = $pdo->prepare("EXPLAIN SELECT * FROM users WHERE status = ?");
$stmt->execute([1]);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($result);
12. 部署与持续集成
12.1 基础部署流程
典型部署步骤:
- 代码上传到服务器
- 安装依赖:
composer install --no-dev - 设置环境变量
- 配置Web服务器(Nginx/Apache)
- 设置文件权限
- 重启服务
12.2 使用Docker部署
基础Dockerfile示例:
dockerfile复制FROM php:8.1-apache
RUN apt-get update && apt-get install -y \
libzip-dev \
zip \
&& docker-php-ext-install zip pdo_mysql
COPY . /var/www/html
RUN chown -R www-data:www-data /var/www/html
13. 测试策略
13.1 PHPUnit基础测试
示例测试类:
php复制use PHPUnit\Framework\TestCase;
class SampleTest extends TestCase {
public function testAddition() {
$this->assertEquals(4, 2+2);
}
public function testDatabaseConnection() {
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$this->assertInstanceOf(PDO::class, $pdo);
}
}
13.2 接口测试
使用GuzzleHTTP测试API:
php复制use GuzzleHttp\Client;
use PHPUnit\Framework\TestCase;
class ApiTest extends TestCase {
public function testGetUser() {
$client = new Client(['base_uri' => 'http://localhost']);
$response = $client->request('GET', '/api/users/1');
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($response->getBody(), true);
$this->assertArrayHasKey('id', $data);
}
}
14. 安全加固措施
14.1 输入过滤
使用filter_var函数:
php复制$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
if(!$email) {
die('无效的邮箱地址');
}
14.2 密码安全
正确存储密码:
php复制// 创建密码哈希
$hash = password_hash($_POST['password'], PASSWORD_DEFAULT);
// 验证密码
if(password_verify($_POST['password'], $hashFromDatabase)) {
// 登录成功
}
14.3 防止XSS攻击
输出转义:
php复制echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
15. 日志记录与分析
15.1 基础日志记录
php复制$logMessage = sprintf(
"[%s] %s %s %s\n",
date('Y-m-d H:i:s'),
$_SERVER['REMOTE_ADDR'],
$_SERVER['REQUEST_METHOD'],
$_SERVER['REQUEST_URI']
);
file_put_contents('access.log', $logMessage, FILE_APPEND);
15.2 使用Monolog
php复制require 'vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$log = new Logger('app');
$log->pushHandler(new StreamHandler('app.log', Logger::WARNING));
$log->warning('用户登录失败', ['username' => $_POST['username']]);
16. 缓存策略
16.1 文件缓存
php复制function getCachedData($key, $ttl = 3600) {
$file = "cache/".md5($key).".cache";
if(file_exists($file) && time()-filemtime($file) < $ttl) {
return unserialize(file_get_contents($file));
}
return false;
}
function setCacheData($key, $data) {
$file = "cache/".md5($key).".cache";
file_put_contents($file, serialize($data));
}
16.2 使用Redis
php复制$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 设置缓存
$redis->setex('user:123', 3600, json_encode($userData));
// 获取缓存
$userData = json_decode($redis->get('user:123'), true);
17. 国际化与本地化
17.1 多语言支持
使用gettext实现:
php复制// 设置语言环境
putenv('LC_ALL=zh_CN');
setlocale(LC_ALL, 'zh_CN');
// 指定翻译文件位置
bindtextdomain('messages', './locale');
textdomain('messages');
// 使用翻译
echo _("Welcome");
17.2 日期时间本地化
php复制$date = new DateTime();
$formatter = new IntlDateFormatter(
'zh_CN',
IntlDateFormatter::FULL,
IntlDateFormatter::FULL,
'Asia/Shanghai',
IntlDateFormatter::GREGORIAN,
'yyyy年MM月dd日 HH:mm:ss'
);
echo $formatter->format($date);
18. 微服务与API网关
18.1 基础API网关实现
php复制// gateway.php
$request = $_SERVER['REQUEST_URI'];
$service = explode('/', $request)[1];
switch($service) {
case 'user':
$response = file_get_contents('http://user-service'.$_SERVER['REQUEST_URI']);
break;
case 'product':
$response = file_get_contents('http://product-service'.$_SERVER['REQUEST_URI']);
break;
default:
http_response_code(404);
$response = json_encode(['error' => 'Service not found']);
}
header('Content-Type: application/json');
echo $response;
18.2 服务发现
php复制// 从Consul获取服务地址
$services = json_decode(file_get_contents('http://consul:8500/v1/catalog/service/user-service'), true);
$service = $services[array_rand($services)];
$url = "http://{$service['ServiceAddress']}:{$service['ServicePort']}/api";
19. 消息队列应用
19.1 使用Redis实现简单队列
php复制$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 生产者
$redis->rpush('email_queue', json_encode([
'to' => 'user@example.com',
'subject' => 'Welcome',
'body' => 'Thank you for registering'
]));
// 消费者
while(true) {
$message = $redis->blpop('email_queue', 30);
if($message) {
$email = json_decode($message[1], true);
// 发送邮件...
}
}
19.2 使用RabbitMQ
php复制// 生产者
$connection = new AMQPConnection(['host' => 'localhost']);
$channel = $connection->channel();
$channel->queue_declare('task_queue', false, true, false, false);
$msg = new AMQPMessage('Hello World!');
$channel->basic_publish($msg, '', 'task_queue');
// 消费者
$callback = function($msg) {
echo "Received: ", $msg->body, "\n";
$msg->ack();
};
$channel->basic_consume('task_queue', '', false, false, false, false, $callback);
20. 现代PHP开发实践
20.1 使用PSR标准
遵循PSR规范:
- PSR-1/PSR-12:代码风格
- PSR-4:自动加载
- PSR-7:HTTP消息接口
- PSR-11:容器接口
20.2 类型声明与严格模式
php复制declare(strict_types=1);
function addNumbers(int $a, int $b): int {
return $a + $b;
}
20.3 使用PHP 8+新特性
php复制// 命名参数
array_map(callback: fn($x) => $x * 2, array: [1, 2, 3]);
// 构造器属性提升
class User {
public function __construct(
public string $name,
protected int $age
) {}
}
// 匹配表达式
$result = match($statusCode) {
200, 201 => 'success',
404 => 'not found',
default => 'unknown'
};
21. 前端构建工具集成
21.1 使用Webpack与PHP配合
webpack.config.js示例:
javascript复制module.exports = {
entry: './assets/js/app.js',
output: {
path: __dirname + '/public/build',
filename: 'bundle.js'
}
};
PHP模板中引用:
php复制<script src="/build/bundle.js"></script>
21.2 热模块替换配置
javascript复制// webpack.config.js
devServer: {
proxy: {
'/': 'http://localhost:8000'
}
}
PHP开发服务器:
bash复制php -S localhost:8000 -t public
22. 微前端架构集成
22.1 基础集成方案
php复制// 主应用模板
function renderMicroFrontend($name) {
$html = file_get_contents("http://{$name}.example.com");
return "<div id='{$name}-container'>{$html}</div>";
}
echo renderMicroFrontend('product');
echo renderMicroFrontend('cart');
22.2 使用Web Components
javascript复制// 前端代码
class UserProfile extends HTMLElement {
connectedCallback() {
fetch('/api/user')
.then(res => res.json())
.then(user => {
this.innerHTML = `<div>
<h3>${user.name}</h3>
<p>${user.email}</p>
</div>`;
});
}
}
customElements.define('user-profile', UserProfile);
PHP模板中直接使用:
html复制<user-profile></user-profile>
23. 性能监控与APM集成
23.1 使用New Relic
安装New Relic PHP agent后:
php复制// 自定义事务
newrelic_start_transaction("my_custom_transaction");
// 你的代码...
newrelic_end_transaction();
// 自定义指标
newrelic_custom_metric("Custom/MyMetric", 42);
23.2 使用Blackfire
配置Blackfire探针后:
php复制// 手动分析代码段
blackfire_start();
// 需要分析的代码
blackfire_end();
24. 无服务器架构应用
24.1 使用Bref部署PHP到AWS Lambda
serverless.yml配置:
yaml复制service: php-app
provider:
name: aws
runtime: provided.al2
plugins:
- serverless-bref
functions:
api:
handler: public/index.php
events:
- httpApi: '*'
24.2 函数实现
php复制// index.php
require __DIR__.'/vendor/autoload.php';
$app = new \Slim\App;
$app->get('/hello/{name}', function ($request, $response, $args) {
return $response->write("Hello ".$args['name']);
});
$app->run();
25. 容器化与编排
25.1 Docker Compose配置
yaml复制version: '3'
services:
app:
build: .
ports:
- "8000:80"
volumes:
- .:/var/www/html
depends_on:
- db
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: app
25.2 Kubernetes部署
基础Deployment配置:
yaml复制apiVersion: apps/v1
kind: Deployment
metadata:
name: php-app
spec:
replicas: 3
selector:
matchLabels:
app: php-app
template:
metadata:
labels:
app: php-app
spec:
containers:
- name: php-app
image: my-php-app:latest
ports:
- containerPort: 80
26. 持续集成与部署
26.1 GitHub Actions配置
yaml复制name: CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
extensions: mbstring, xml, mysql, gd
- name: Install dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Run tests
run: vendor/bin/phpunit
26.2 部署流程
yaml复制deploy:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install SSH key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_PRIVATE_KEY }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: Deploy to server
run: |
rsync -avz --delete ./ user@server:/var/www/html/
ssh user@server "cd /var/www/html && composer install --no-dev"
27. 现代化PHP项目结构
27.1 推荐目录结构
code复制project/
├── app/ # 应用代码
│ ├── Controllers/ # 控制器
│ ├── Models/ # 数据模型
│ ├── Services/ # 业务服务
│ └── Middleware/ # 中间件
├── config/ # 配置文件
├── public/ # Web根目录
│ └── index.php # 入口文件
├── resources/ # 前端资源
│ ├── views/ # 模板文件
│ └── assets/ # 静态资源
├── routes/ # 路由定义
├── storage/ # 存储
│ ├── cache/ # 缓存
│ ├── logs/ # 日志
│ └── sessions/ # 会话
├── tests/ # 测试代码
├── vendor/ # Composer依赖
├── .env # 环境变量
└── composer.json # 依赖管理
27.2 环境配置管理
使用vlucas/phpdotenv:
php复制// 加载.env文件
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
// 获取配置
$dbHost = $_ENV['DB_HOST'];
28. 现代化认证方案
28.1 JWT认证实现
生成JWT令牌:
php复制use Firebase\JWT\JWT;
$key = $_ENV['JWT_SECRET'];
$payload = [
'iss' => 'your-issuer',
'aud' => 'your-audience',
'iat' => time(),
'exp' => time() + 3600,
'userId' => 123
];
$jwt = JWT::encode($payload, $key, 'HS256');
验证JWT令牌:
php复制try {
$decoded = JWT::decode($jwt, $_ENV['JWT_SECRET'], ['HS256']);
$userId = $decoded->userId;
} catch(Exception $e) {
http_response_code(401);
die('Invalid token');
}
28.2 OAuth2集成
使用league/oauth2-client:
php复制$provider = new League\OAuth2\Client\Provider\GenericProvider([
'clientId' => $_ENV['OAUTH_CLIENT_ID'],
'clientSecret' => $_ENV['OAUTH_CLIENT_SECRET'],
'redirectUri' => $_ENV['OAUTH_REDIRECT_URI'],
'urlAuthorize' => 'https://provider.com/oauth2/auth',
'urlAccessToken' => 'https://provider.com/oauth2/token',
'urlResourceOwnerDetails' => 'https://provider.com/oauth2/userinfo'
]);
// 获取授权URL
$authUrl = $provider->getAuthorizationUrl();
$_SESSION['oauth2state'] = $provider->getState();
header('Location: '.$authUrl);
29. 现代化缓存策略
29.1 多级缓存实现
php复制class CacheManager {
private $fastCache; // Redis
private $slowCache; // 文件/数据库
public function get($key) {
$data = $this->fastCache->get($key);
if($data === false) {
$data = $this->slowCache->get($key);
if($data !== false) {
$this->fastCache->set($key, $data, 3600);
}
}
return $data;
}
}
29.2 缓存标签实现
php复制// 使用Redis实现标签
function getWithTag($key, $tag) {
$tagKey = "tag:{$tag}";
$itemKey = $redis->hGet($tagKey, $key);
return $itemKey ? $redis->get($itemKey) : false;
}
function setWithTag($key, $value, $tag, $ttl = 3600) {
$tagKey = "tag:{$tag}";
$itemKey = "item:".md5($key);
$redis->hSet($tagKey, $key, $itemKey);
$redis->setex($itemKey, $ttl, $value);
}
function invalidateTag($tag) {
$tagKey = "tag:{$tag}";
$items = $redis->hGetAll($tagKey);
foreach($items as $itemKey) {
$redis->del($itemKey);
}
$redis->del($tagKey);
}
30. 现代化日志实践
30.1 结构化日志
php复制$logger->info('User logged in', [
'userId' => 123,
'ip' => $_SERVER['REMOTE_ADDR'],
'userAgent' => $_SERVER['HTTP_USER_AGENT']
]);
30.2 日志上下文
php复制// 创建带有请求ID的日志上下文
$requestId = bin2hex(random_bytes(8));
$logger->pushProcessor(function($record) use ($requestId) {
$record['extra']['request_id'] = $requestId;
return $record;
});
// 所有日志都会自动包含request_id
$logger->info('Processing request');
31. 现代化错误处理
31.1 异常处理器
php复制set_exception_handler(function($exception) {
$logger->error($exception->getMessage(), [
'exception' => $exception,
'trace' => $exception->getTrace()
]);
http_response_code(500);
echo json_encode(['error' => 'Internal Server Error']);
});
set_error_handler(function($level, $message, $file, $line) {
throw new ErrorException($message, 0, $level, $file, $line);
});
31.2 优雅降级
php复制try {
$result = $someService->doSomething();
} catch(ServiceUnavailableException $e) {
// 从缓存获取旧数据
$result = $cache->get('fallback_data');
// 记录降级事件
$logger->warning('Service unavailable, using fallback data', [
'error' => $e->getMessage()
]);
}
32. 现代化测试策略
32.1 契约测试
php复制// 消费者测试
class ConsumerTest extends TestCase {
public function testUserApiContract() {
$client = new Client(['base_uri' => 'http://user-service']);
$response = $client->get('/users/1');
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($response->getBody(), true);
$this->assertArrayHasKey('id', $data);
$this->assertArrayHasKey('name', $data);
}
}
32.2 模拟服务
php复制// 使用Mockery模拟服务
$userService = Mockery::mock(UserService::class);
$userService->shouldReceive('findById')
->with(1)
->andReturn(['id' => 1, 'name' => 'Mock User']);
$controller = new UserController($userService);
$response = $controller->show(1);
$this->assertEquals(200, $response->getStatusCode());
33. 现代化部署策略
33.1 蓝绿部署
bash复制# 部署新版本到绿色环境
scp -r build/ user@server:/var/www/green
# 切换负载均衡
ssh user@server "ln -sfn /var/www/green /var/www/current"
# 保留蓝色环境以备回滚
33.2 金丝雀发布
php复制// 根据用户ID分流通往不同版本
if($userId % 10 < 2) { // 20%流量到新版本
$response = file_get_contents('http://new-version/api');
} else {
$response = file_get_contents('http://old-version/api');
}
34. 现代化监控策略
34.1 健康检查端点
php复制// health.php
header('Content-Type: application/json');
$checks = [
'database' => checkDatabase(),
'cache' => checkCache(),
'external_service' => checkExternalService()
];
$status = !in_array(false, $checks, true) ? 'healthy' : 'degraded';
http_response_code($status === 'healthy' ? 200 : 503);
echo json_encode([
'status' => $status,
'checks' => $checks
]);
function checkDatabase() {
try {
$pdo = new PDO($_ENV['DB_DSN'], $_ENV['DB_USER'], $_ENV['DB_PASS']);
return (bool)$pdo->query('SELECT 1');
} catch(PDOException $e) {
return false;
}
}
34.2 指标端点
php复制// metrics.php
header('Content-Type: text/plain');
echo "# HELP php_requests_total Total requests\n";
echo "# TYPE php_requests_total counter\n";
echo "php_requests_total ".getTotalRequests()."\n";
function getTotalRequests() {
// 从Redis或共享内存获取
return apcu_fetch('total_requests') ?: 0;
}
35. 现代化安全实践
35.1 CSP策略
php复制header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:;");
35.2 安全头设置
php复制header("X-Frame-Options: DENY");
header("X-Content-Type-Options: nosniff");
header("Referrer-Policy: strict-origin-when-cross-origin");
header("Feature-Policy: geolocation 'none'; microphone 'none'");
36. 现代化API设计
36.1 HATEOAS实现
php复制// 返回带有链接的资源
$user = [
'id' => 123,
'name' => 'John Doe',
'_links' => [
'self' => ['href' => '/users/123'],
'orders' => ['href' => '/users/123/orders']
]
];
echo json_encode($user);
36.2 版本控制
php复制// 通过Accept头进行版本控制
$accept = $_SERVER['HTTP_ACCEPT'] ?? '';
if(strpos($accept, 'application/vnd.api.v2+json') !== false) {
// 返回v2格式
} else {
// 默认v1格式
}
