You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Herd自定义Valet驱动路径解析异常求助

原生PHP项目Laravel Herd路径解析问题排查

问题背景

在原生PHP项目中使用Laravel Herd时,遇到以下路径解析问题:

  • 系统仅识别index.php文件,访问http://x.test/case-studies无法自动解析到case-studies.php,为此实现了自定义Valet驱动解决该问题。
  • 访问http://x.test/services/时,本该路由到services/index.php却出现404错误。

错误日志

错误1

2025/03/05 10:45:18 [error] 90478#1248117: *34 "Users/jack-brogan/Herd/x/html/services//index.html" is not found (2: No such file or directory), client: 127.0.0.1, server: , request: "GET /services/ HTTP/1.1", upstream: "fastcgi://unix:/Users/jack-brogan/Library/Application Support/Herd/herd.sock", host: "x.test", referrer: "

疑问:路径末尾出现双斜杠,且系统查找index.html而非index.php。

错误2

2025/03/05 10:45:18 [error] 90478#1248117: *34 FastCGI sent in stderr: "PHP message: Servers is truePHP message: Current site path: /Users/jack-brogan/Herd/x/htmlPHP message: Current URI: /favicon.icoPHP message: Raw URI: /favicon.icoPHP message: sitepath 1: /Users/jack-brogan/Herd/x/html/favicon.ico.phpPHP message: sitepath 2: /Users/jack-brogan/Herd/x/html/favicon.ico/index.php" while reading response header from upstream, client: 127.0.0.1, server: , request: "GET /favicon.ico HTTP/1.1", upstream: "fastcgi://unix:/Users/jack-brogan/Library/Application Support/Herd/herd.sock:", host: "x.test", referrer: "http://x.test/services/"

自定义驱动代码(原版本)

// namespace Valet\Drivers;

use Valet\Drivers\ValetDriver;

class LocalValetDriver extends ValetDriver
{
    /**
     * Determine if the driver serves the request.
     */
    public function serves(string $sitePath, string $siteName, string $uri): bool
    {
        if (file_exists($sitePath . '/index.php')) {
            return true;
        }
        return true;
        // return file_exists($sitePath . $uri . '.php');
    }

    /**
     * Resolve the incoming request to a valid PHP script.
     */
    public function isStaticFile($sitePath, $siteName, $uri)
    {
        if (file_exists($staticFilePath = $sitePath . $uri)) {
            return $staticFilePath;
        }

        return false;
    }

    /**
     * Directs Nginx to the correct file.
     */
    public function frontControllerPath(string $sitePath, string $siteName, string $uri): string
    {

        error_log("Current site path: " . $sitePath);
        error_log("Current URI: " . $uri);
        error_log("Raw URI: " . $_SERVER['REQUEST_URI']);
        
        // Check if request is for a PHP file
        if (file_exists($sitePath . $uri . '.php')) {
            return $sitePath . $uri . '.php';
        }

        // Default to index.php if no other match is found
        return $sitePath . $uri . '/index.php'; // Ensure correct path to index.php
    }
}

问题定位与解决

核心问题分析

  1. 双斜杠问题:当访问/services/时,$uri值为/services/,直接拼接$sitePath . $uri . '/index.php'会生成/.../services//index.php,导致路径出现双斜杠。
  2. index.html优先级问题:Nginx默认会优先查找静态index.html文件,当前驱动未正确拦截目录请求,导致Nginx先尝试静态文件而非交给PHP处理。
  3. 静态文件误处理:favicon.ico这类静态文件未被isStaticFile正确识别,进入了frontControllerPath方法,被错误拼接成.php文件路径。

修正后的驱动代码

use Valet\Drivers\ValetDriver;

class LocalValetDriver extends ValetDriver
{
    /**
     * 判断驱动是否处理当前请求
     */
    public function serves(string $sitePath, string $siteName, string $uri): bool
    {
        return file_exists($sitePath . '/index.php');
    }

    /**
     * 识别静态文件,避免进入PHP处理流程
     */
    public function isStaticFile($sitePath, $siteName, $uri)
    {
        // 定义常见静态文件后缀
        $staticExtensions = ['html', 'css', 'js', 'png', 'jpg', 'jpeg', 'gif', 'ico', 'svg'];
        $pathInfo = pathinfo($sitePath . $uri);
        
        // 检查是否为静态文件且存在
        if (isset($pathInfo['extension']) && in_array(strtolower($pathInfo['extension']), $staticExtensions)) {
            $staticFilePath = $sitePath . $uri;
            if (file_exists($staticFilePath)) {
                return $staticFilePath;
            }
        }

        return false;
    }

    /**
     * 解析请求到对应的PHP文件
     */
    public function frontControllerPath(string $sitePath, string $siteName, string $uri): string
    {
        // 标准化URI:去除末尾斜杠,避免双斜杠
        $uri = rtrim($uri, '/');

        // 处理目录请求:检查目录下的index.php
        if ($uri !== '' && is_dir($sitePath . $uri)) {
            $indexPath = $sitePath . $uri . '/index.php';
            if (file_exists($indexPath)) {
                return $indexPath;
            }
        }

        // 处理无后缀请求:映射到对应的.php文件
        if (file_exists($sitePath . $uri . '.php')) {
            return $sitePath . $uri . '.php';
        }

        // 默认返回根目录index.php(可根据项目需求调整)
        return $sitePath . '/index.php';
    }
}

关键修改说明

  • isStaticFile方法:新增静态文件后缀判断,确保favicon.ico、图片、CSS等静态文件被正确识别,不会进入PHP处理流程。
  • frontControllerPath方法:
    • 用rtrim($uri, '/')去除URI末尾的斜杠,解决双斜杠拼接问题。
    • 优先处理目录请求:先判断URI是否对应一个目录,若存在则返回目录下的index.php,解决/services/路由到services/index.php的问题。
    • 调整逻辑顺序:先处理目录,再处理无后缀文件,最后 fallback到根目录index.php,符合常规请求解析逻辑。
  • serves方法:简化逻辑,仅当项目根目录存在index.php时才处理请求,避免不必要的判断。

内容的提问来源于stack exchange,提问作者jbrogan99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 03:28:11