本文目录导读:

- 本地开发 / 传统部署(Apache / Nginx)
- 使用 PHP 内置服务器(开发环境)
- 使用 PHP 框架的路由实现静态文件托管
- 外部 CDN 托管(生产环境推荐)
- 安全与性能优化建议
- Docker 容器化部署
在 PHP 中托管静态资源(如图片、CSS、JS、字体等),主要有以下几种方案,具体取决于你的项目类型和部署环境。
本地开发 / 传统部署(Apache / Nginx)
✅ 最佳实践:使用 Web 服务器直出静态文件
不通过 PHP 处理静态文件,而是让 Web 服务器(Nginx/Apache)直接返回静态文件。
Nginx 配置(推荐)
server {
listen 80;
server_name example.com;
root /var/www/html/public;
# PHP 请求转发给 PHP-FPM
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 静态文件直接返回,不经过 PHP
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
try_files $uri =404;
}
}
Apache 配置(.htaccess)
<IfModule mod_rewrite.c>
RewriteEngine On
# 如果是真实存在的静态文件,直接返回
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# 否则转发给 PHP 入口文件
RewriteRule ^ index.php [L]
</IfModule>
使用 PHP 内置服务器(开发环境)
# 启动内置服务器,将静态文件放在 public 目录下 php -S localhost:8000 -t public # 或者用路由文件(需要在 public 目录下创建 router.php) php -S localhost:8000 public/router.php
router.php 示例:
<?php
// 获取请求的文件路径
$path = __DIR__ . '/' . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// 如果是真实存在的文件,直接返回(不走 PHP 框架)
if (is_file($path)) {
return false;
}
// 否则走入口文件
require __DIR__ . '/index.php';
使用 PHP 框架的路由实现静态文件托管
Laravel
// routes/web.php
Route::get('/static/{file}', function ($file) {
$path = storage_path('app/public/' . $file);
if (file_exists($path)) {
return response()->file($path);
}
abort(404);
})->where('file', '.*');
Symfony
// 使用 Symfony 的文件监听器
use Symfony\Component\HttpFoundation\BinaryFileResponse;
Route::get('/static/{file}', function ($file) {
$path = __DIR__ . '/../storage/' . $file;
if (file_exists($path)) {
return new BinaryFileResponse($path);
}
abort(404);
})->where('file', '.*');
外部 CDN 托管(生产环境推荐)
使用阿里云OSS / 腾讯云COS + CDN
// 配置静态资源 URL
class StaticConfig {
public static $cdnBase = 'https://cdn.example.com';
public static function asset($path) {
return self::$cdnBase . '/' . ltrim($path, '/');
}
}
// 使用
echo '<link rel="stylesheet" href="' . StaticConfig::asset('css/app.css') . '">';
使用七牛云 / 又拍云
// 上传后返回 CDN 地址 $qn = new Qiniu\Storage\UploadManager(); $result = $qn->put(token, $key, $fileContent); $cdnUrl = 'https://cdn.example.com/' . $key;
安全与性能优化建议
安全防护
// 防止目录穿越
$file = base64_decode(request('file'));
$realPath = realpath(storage_path() . '/' . $file);
$allowedPath = realpath(storage_path());
if (!$realPath || strpos($realPath, $allowedPath) !== 0) {
abort(403);
}
缓存头设置
// 设置长缓存
$response = response()->file($path, [
'Cache-Control' => 'public, max-age=31536000',
'Expires' => gmdate('D, d M Y H:i:s T', time() + 31536000),
]);
// 添加 ETag
$etag = md5_file($path);
$response->setEtag($etag);
$response->isNotModified(request());
Docker 容器化部署
# 多阶段构建 FROM composer:2 AS build WORKDIR /app COPY . . RUN composer install --no-dev FROM php:8.2-fpm AS app COPY --from=build /app /var/www # 使用 Nginx 直接服务静态文件,PHP-FPM 只处理 PHP
server {
listen 80;
# 静态文件直接由 Nginx 服务
location /static/ {
alias /var/www/public/static/;
}
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
}
}
| 场景 | 推荐方案 |
|---|---|
| 传统部署 | Web 服务器直出(性能最好) |
| 开发环境 | PHP 内置服务器 + router.php |
| 小型项目 | 框架路由托管(注意安全验证) |
| 中大型项目 | CDN + 云存储(阿里云OSS等) |
| 容器化部署 | Nginx 容器直出静态文件 |
最重要的原则:不要让 PHP 处理静态文件请求,交给专业的 Web 服务器或 CDN,性能会好得多。