带参数的PHP API路由

后端开发 2026-07-09

我在一个PHP路由类中有如下路由:

$router->add('/public/bookings/get/{id}', array(
    'controller' => 'Bookings',
    'action' => 'getBookingId'
));

如何在Router类中实现用于路由选择的正则逻辑?我有如下代码,但它没有匹配:

foreach ($this->routes as $route => $params) {
    $pattern = str_replace(['{id}','/'], ['([0-9]+)', '\/'],$route);

    if(preg_match($pattern, $url['path'])) {
        $this->params = $params;
    }
}

解决方案

foreach ($this->routes as $route => $params) {
    $pattern = str_replace('{id}', '([0-9]+)', $route);

    // Wrap the pattern in delimiters (#) and add anchors (^ and $) 
    // so it matches the entire url, not just a subset.
    $regex = '#^' . $pattern . '$#';

    if (preg_match($regex, $url['path'], $matches)) {
        $this->params = $params;

        // Small Bonus: The actual ID matched will be in $matches[1]
        $this->params['id'] = $matches[1]; 
        break; // Stop looping once we find a match
    }
}

备选方案

{id} 专门设计的正则看起来比较局限。最好有一个通用的匹配,将 {name} 模式替换成一个命名正则

foreach ($this->routes as $route => $caller) {
    $pattern = "#^" . preg_replace('/\{([a-zA-Z0-9_]+)\}/', '(?P<$1>[^/]+)', $path) . "$#";

    if (preg_match($pattern, $url['path'], $matches)) {
        // Filter out numeric keys from preg_match to keep only named params
        $params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
        return [$caller['controller'],$caller['action']](...$params);
    }
}

在这里,相应的类和方法被称为 $caller,而URL中提供的参数被称为 $params。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章