
本文详解PHP项目中“public/”与“src/”分离结构下表单action路径配置错误导致404的根本原因,涵盖浏览器路径解析机制、Web服务器路由逻辑、安全架构原则及四种生产就绪的路径管理方案。
本文详解php项目中“public/”与“src/”分离结构下表单`action`路径配置错误导致404的根本原因,涵盖浏览器路径解析机制、web服务器路由逻辑、安全架构原则及四种生产就绪的路径管理方案。
在现代PHP项目(如To-Do应用)中,采用「前端入口隔离」架构——将public/设为Web服务器唯一可公开访问目录,而src/、database/等敏感目录置于其外——是基础安全实践。但这一设计恰恰会引发新手最典型的404问题:表单提交至src/create.php时浏览器报错“URL未找到”,并非代码有误,而是路径语义被双重误解。
? 根本原因:浏览器 vs 服务器的路径认知鸿沟
你的HTML中写的是:
<form method="POST" action="src/create.php">
⚠️ 这个action值是相对URL路径,其解析完全由浏览器执行,且以当前页面URL为基准,而非文件系统目录结构。
假设你通过 http://localhost/public/index.php 访问页面:
立即学习“PHP免费学习笔记(深入)”;
- 浏览器会将
action="src/create.php"解析为http://localhost/public/src/create.php - Apache收到该请求后,在网站根目录(如
C:\xampp\htdocs\)下查找public/src/create.php—— 但你的src/目录实际位于public/同级!因此必然404。
更关键的是:src/目录本就不应被Web服务器直接访问。这是刻意为之的安全设计——若Apache能响应/src/create.php,攻击者即可直接请求/src/database/conn_db.php窃取数据库凭证。真正的解决方案不是“让src可访问”,而是让请求经由public/入口代理到内部逻辑。
✅ 正确解法:统一入口 + 后端路由转发
方案1:重写表单action为绝对路径(开发阶段快速验证)
将action改为指向public/下的一个代理脚本(推荐):
<!-- public/index.php --> <form method="POST" action="/public/handler.php">
然后在 public/handler.php 中:
<?php // public/handler.php —— 唯一公开入口 require_once __DIR__ . '/../src/create.php'; // 安全包含,不暴露src路径
✅ 优势:路径清晰、无跨域风险、符合PSR-4规范;❌ 注意:需确保Apache支持.htaccess重写或Nginx配置try_files。
方案2:使用环境感知的路径生成函数(推荐生产用)
创建 config/common.php:
<?php
// config/common.php
define('APP_ENV', $_SERVER['HTTP_HOST'] === 'localhost' ? 'dev' : 'prod');
define('BASE_URL', APP_ENV === 'dev'
? 'http://localhost'
: 'https://yourdomain.com');在HTML中动态生成action:
<form method="POST" action="<?= BASE_URL ?>/public/handler.php">
方案3:通过.htaccess重写隐藏真实路径(Apache专属)
在public/.htaccess中添加:
# 将 /api/create 转发到内部处理脚本 RewriteRule ^api/create$ ../src/create.php [L]
表单改为:
<form method="POST" action="/public/api/create">
方案4:现代方案——使用PHP内置服务器或反向代理
- 开发时:用
php -S localhost:8000 router.php启动,router.php定义路由逻辑; - 生产时:Nginx配置
location /api/ { proxy_pass http://php-fpm; },将API请求转发至PHP-FPM容器。
⚠️ 必须规避的危险操作
- ❌ 不要设置
<form action="../src/create.php"></form>:..在URL中无效,浏览器禁止向上跳转; - ❌ 不要在Apache中开放
src/目录权限:这等于放弃安全隔离; - ❌ 避免硬编码
localhost/src/:本地测试可行,但部署到example.com时立即失效; - ❌ 禁止在
create.php中直接输出HTML:它应只处理逻辑并重定向,UI由public/层统一控制。
? 调试黄金步骤(5分钟定位)
- 打开浏览器开发者工具 → Network标签页,提交表单,观察红色404请求的Request URL(这才是真相);
-
对比该URL与Apache虚拟主机
DocumentRoot设置(XAMPP默认是htdocs); -
检查Apache错误日志(
error.log),搜索File does not exist确认实际查找路径; -
在
create.php顶部临时加入:<?php error_log("SCRIPT_FILENAME: " . $_SERVER['SCRIPT_FILENAME']); ?>查看日志中PHP实际加载的文件路径。
? 终极原则:Web服务器只能响应
public/及其子目录下的请求;所有业务逻辑必须通过public/入口进入,再由PHP内部require调用隔离目录中的文件。 这不是限制,而是纵深防御的第一道防火墙。
遵循此架构,你的To-Do应用既能抵御路径遍历攻击,又能优雅支持本地开发与多环境部署——404将不再是障碍,而是安全策略生效的证明。



















