PHP 路由器、.htaccess 和重写查询字符串
PHP Router, .htaccess and rewriting query string
我尝试搜索这个问题,但没有找到解决我问题的方法 - 我几乎可以肯定我没有输入正确的搜索,因为我想这对其他人来说也是一个问题。如果我在打死马,请指出正确的方向,谢谢。
现有代码
我正在构建一种 MVC 框架。
.htaccess 将所有请求路由到 index.php.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ index.php [QSA,L]
<?php
require_once "./core/init.php";
Router::create( "./core/router/routes.php" )->direct( Request::uri(), Request::method() );
我的router.class.php文件:
<?php
class Router {
protected $routes = array(
"GET" => array(),
"POST" => array()
);
public static function create( $routes ) {
$router = new static;
include $routes;
return $router;
}
public function get( $uri, $controller ) {
$this->routes[ "GET" ][ $uri ] = $controller;
}
public function post( $uri, $controller ) {
$this->routes[ "POST" ][ $uri ] = $controller;
}
public function direct( $uri, $method ) {
if ( array_key_exists( $uri, $this->routes[ $method ] ) ) {
include $this->routes[ $method ][ $uri ];
} else {
include $this->routes[ "GET" ][ "not-found" ];
}
}
}
路由在routes.php中定义如下(仅显示相关路由):
$router->get( "post", "controllers/get/post.controller.php" );
我的问题
当前导航到下面显示 post 并且 post 是使用 slug 从数据库中检索的。
/post?p=my-post-name
我如何重写我的路由器或 .htaccess 以具有与以下 URL 相同的 post?
/post/my-post-name
所以最后我通过在引导路由器之前创建检查解决了这个问题,但不确定这是否是 "right" 方式。
这基本上是根据数组检查 URI,如果 URI 包含这些设置值之一,则将其解构,最后一个值存储在名为 get
的变量中,然后重建 URI 减去假查询字符串:
// index.php
require_once "./core/init.php";
$uri = Request::uri();
/*
* Fake query strings
*/
$uriParts = explode( "/", $uri );
$queryPages = array( "post", "category", "edit-post" );
foreach ( $queryPages as $queryPage ) {
if ( in_array( $queryPage, $uriParts ) ) {
$get = $uriParts[ count( $uriParts ) - 1 ];
array_pop( $uriParts );
$uri = "";
for ( $i = 0; $i < ( count( $uriParts ) ); $i++ ) {
$uri .= $uriParts[ $i ] . "/";
}
$uri = trim( $uri, "/" );
break;
}
}
Router::create( "./core/router/routes.php" )->direct( $uri, Request::method() );
以上适用于各种深度的 URI:
post/my-post
category/general
admin/posts/edit-post/my-post
"query string" 可以在带有 global $get;
的控制器中使用,然后用来代替 $_GET
。这不适用于多个查询,但它非常适合我的要求。
我尝试搜索这个问题,但没有找到解决我问题的方法 - 我几乎可以肯定我没有输入正确的搜索,因为我想这对其他人来说也是一个问题。如果我在打死马,请指出正确的方向,谢谢。
现有代码
我正在构建一种 MVC 框架。
.htaccess 将所有请求路由到 index.php.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ index.php [QSA,L]
<?php
require_once "./core/init.php";
Router::create( "./core/router/routes.php" )->direct( Request::uri(), Request::method() );
我的router.class.php文件:
<?php
class Router {
protected $routes = array(
"GET" => array(),
"POST" => array()
);
public static function create( $routes ) {
$router = new static;
include $routes;
return $router;
}
public function get( $uri, $controller ) {
$this->routes[ "GET" ][ $uri ] = $controller;
}
public function post( $uri, $controller ) {
$this->routes[ "POST" ][ $uri ] = $controller;
}
public function direct( $uri, $method ) {
if ( array_key_exists( $uri, $this->routes[ $method ] ) ) {
include $this->routes[ $method ][ $uri ];
} else {
include $this->routes[ "GET" ][ "not-found" ];
}
}
}
路由在routes.php中定义如下(仅显示相关路由):
$router->get( "post", "controllers/get/post.controller.php" );
我的问题
当前导航到下面显示 post 并且 post 是使用 slug 从数据库中检索的。
/post?p=my-post-name
我如何重写我的路由器或 .htaccess 以具有与以下 URL 相同的 post?
/post/my-post-name
所以最后我通过在引导路由器之前创建检查解决了这个问题,但不确定这是否是 "right" 方式。
这基本上是根据数组检查 URI,如果 URI 包含这些设置值之一,则将其解构,最后一个值存储在名为 get
的变量中,然后重建 URI 减去假查询字符串:
// index.php
require_once "./core/init.php";
$uri = Request::uri();
/*
* Fake query strings
*/
$uriParts = explode( "/", $uri );
$queryPages = array( "post", "category", "edit-post" );
foreach ( $queryPages as $queryPage ) {
if ( in_array( $queryPage, $uriParts ) ) {
$get = $uriParts[ count( $uriParts ) - 1 ];
array_pop( $uriParts );
$uri = "";
for ( $i = 0; $i < ( count( $uriParts ) ); $i++ ) {
$uri .= $uriParts[ $i ] . "/";
}
$uri = trim( $uri, "/" );
break;
}
}
Router::create( "./core/router/routes.php" )->direct( $uri, Request::method() );
以上适用于各种深度的 URI:
post/my-post
category/general
admin/posts/edit-post/my-post
"query string" 可以在带有 global $get;
的控制器中使用,然后用来代替 $_GET
。这不适用于多个查询,但它非常适合我的要求。