如何从路由器制作漂亮的重写网址
我正在为 php 应用程序制作一个工具包.我已经根据一些约定制作了一个路由系统,它运行良好,但我想学习如何制定 mod_rewrite 规则或任何其他东西,以最终使 url 易于查看并有利于 seo.
I'm making a toolkit for php applications. I've a made a routing system based on some conventions, it works well but i would like to learn how to make mod_rewrite rules or any other stuff to finally make the url good to see and good for seo.
路由系统从设置应用程序和 URL 根的配置文件开始.
The route system starts from a config file that set the app and url roots.
$app_root = $_SERVER["DOCUMENT_ROOT"].dirname($_SERVER["PHP_SELF"])."/";
$app_url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/';
define("APP_URL",$app_url);
define("APP_ROOT",$app_root);
路由总是从 index.php 开始,从 GET 参数中生成控制器@actions 的实例 controller=?&action=?
The route always get start from index.php, wich makes instances of controllers@actions from GET parameters controllers=?&action=?
这是 index.php
This is the index.php
<?php
include_once 'controller/Frontend.php';
require 'libraries/Router.php';
$params=array();
if(isset($_GET['controller'])&&isset($_GET['action'])){
$c = $_GET['controller'];
$a = $_GET['action'];
// add all query string additional params to method signature i.e. &id=x&category=y
$queryParams = array_keys($_GET);
$queryValues = array_values($_GET);
for ($i=2;$i<count($queryParams);$i++) {
$params[$queryParams[$i]] = $queryValues[$i];
}
if ($_POST) {
// add all query string additional params to method signature i.e. &id=x&category=y
$queryParams = array_keys($_POST);
$queryValues = array_values($_POST);
for ($i=0;$i<count($_POST);$i++) {
$params[$queryParams[$i]] = $queryValues[$i];
}
}
include_once APP_ROOT."/controller/$c.php";
$controller = new $c();
$controller->$a($params);
} else {
//attiva controller predefinito
$controller = new Frontend();
$controller->index();
}
这允许选择路由器必须调用的控制器和动作.
This allow to select what controller and what action the router must call.
这里的router函数是从root中的settings.php获取APP URL.你给我两个controller@action params作为字符串,它使URL像这样:index.php?controller=X&action=Y&[params...]
The router function here get the APP URL from settings.php in the root. You give im the two controllers@action params as string and it make the URL like so: index.php?controller=X&action=Y&[params...]
<?php
需要'./settings.php';
require './settings.php';
function router($controller,$action,$query_data="") {
$param = is_array($query_data) ? http_build_query($query_data) : "$query_data";
$url = APP_URL."index.php?controller=$controller&action=$action&$param";
return $url;
}
function relativeRouter ($controller,$action,$query_data=""){
$param = is_array($query_data) ? http_build_query($query_data) : "$query_data";
$url = "index.php?controller=$controller&action=$action&$param";
return $url;
}
function redirectToOriginalUrl() {
$url = $_SERVER['HTTP_REQUEST_URI'];
header("location: $url");
}
function switchAction ($controller, $action) {
$r = router($controller, $action);
header("location:$r", true, 302);
}
在模板文件中,我调用 router('controller,'action') 来检索动作的 url 并传递 GET/POST 数据(从 index.php 收集,将它们作为数组放入方法签名中).
In templates file i call router('controller,'action') to retrive url's to actions and also pass GET/POST data (collected from index.php that put's them into the method signature as array).
不要怪我在没有过滤的情况下使用全局 POST/GET 我还在开发这个东西,之后会做安全事情;)
我想问一下是否有人可以分享一些关于如何制作漂亮的网址(如站点/页面/操作)的想法....例如 www.site.com/blog/post?id=1
What i would like to ask if someone could share some thoughts on how to make pretty urls like site/page/action.... For example www.site.com/blog/post?id=1
(实际上路由器函数($query_data)中的 N 个参数是这样工作的,你传递 array['id' => '1'] 并且你得到 ?id=1)
(Actually the N params in the router function ($query_data) works this way, you pass array['id' => '1'] and you get ?id=1)
制作好网址的最佳策略是什么?非常感谢,还在学习PHP.
What are best strategies to make good urls? Thank you so much, still learning PHP.
如果有最好的方法来做这些事情,请提供您的反馈.
If there are best way to do such things just give your feedback.
推荐答案
我找到了这个问题的答案,我在这里发帖也许有用.
I found myself an answer to the question, i post here maybe it's useful.
我在根目录中添加了一个 .htaccess 文件:
I've added a .htaccess file in the root:
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
这会将每个请求返回到 root/index.php 文件.
This will return each request to the root/index.php file.
索引文件收集来自HTTP请求的路由,检查路由是否存在于routes.json"文件中.
Index file collect routes from the HTTP request, check if the route exist in the "routes.json" file.
URL 是这样写的:site.com/controller/action.GET参数写成如下site.com/controller/action/[params]/[value]......这个输出例如site.com/blog/post/id/1这对于 REST 也应该没问题.
URL are written in this way: site.com/controller/action. GET params are written as follows site.com/controller/action/[params]/[value]...... This output for example site.com/blog/post/id/1 That should be also fine for REST.
这里是 index.php
Here the index.php
<?php
require 'controller/Frontend.php';
require 'Class/Router.php';
//require 'libraries/Router.php';
/*
* ** ROUTING SETTINGS **
*/
$app_root = $_SERVER["DOCUMENT_ROOT"].dirname($_SERVER["PHP_SELF"])."/";
$app_url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/';
define("APP_URL",$app_url);
define("APP_ROOT",$app_root);
$basepath = implode('/', array_slice(explode('/', $_SERVER['SCRIPT_NAME']), 0, -1));
$uri = substr($_SERVER['REQUEST_URI'], strlen($basepath));
//echo $uri;
if ($uri == "/") {
$frontend = new Frontend();
$frontend->index();
} else {
$root = ltrim ($uri, '/');
//$paths = explode("/", $uri);
$paths = parse_url($root, PHP_URL_PATH);
$route = explode("/",$paths);
$request = new PlayPhpClassesRequest();
// controller
$c = $route[0];
// action
$a = $route[1];
$reverse = Router::inverseRoute($c,$a);
$rest = $_SERVER['REQUEST_METHOD'];
switch ($rest) {
case 'PUT':
//rest_put($request);
break;
case 'POST':
if (Router::checkRoutes($reverse, "POST")) {
foreach ($_POST as $name => $value) {
$request->setPost($name,$value);
}
break;
} else {
Router::notFound($reverse,"POST");
}
case 'GET':
if (Router::checkRoutes($reverse, "GET")) {
for ($i = 2; $i < count($route); $i++) {
$request->setGet($route[$i], $route[++$i]);
}
break;
} else {
Router::notFound($reverse,"GET");
}
break;
case 'HEAD':
//rest_head($request);
break;
case 'DELETE':
//rest_delete($request);
break;
case 'OPTIONS':
//rest_options($request);
break;
default:
//rest_error($request);
break;
}
include_once APP_ROOT.'controller/'.$c.'.php';
$controller = new $c();
$controller->$a($request);
}
路由器类:
<?php
include 'config/app.php';
/*
* Copyright (C) 2015 yuri.blanc
*/
require 'Class/http/Request.php';
class Router {
protected static $routes;
private function __construct() {
Router::$routes = json_decode(file_get_contents(APP_ROOT.'config/routes.json'));
}
public static function getInstance(){
if (Router::$routes==null) {
new Router();
}
return Router::$routes;
}
public static function go($action,$params=null) {
$actions = explode("@", $action);
$c = strtolower($actions[0]);
$a = strtolower($actions[1]);
// set query sting to null
$queryString = null;
if(isset($params)) {
foreach ($params as $name => $value) {
$queryString .= '/'.$name.'//'.$value;
}
return APP_URL."$c/$a$queryString";
}
return APP_URL."$c/$a";
}
public static function checkRoutes($action,$method){
foreach (Router::getInstance()->routes as $valid) {
/* echo $valid->action . ' == ' . $action . '|||';
echo $valid->method . ' == ' . $method . '|||';*/
if ($valid->method == $method && $valid->action == $action) {
return true;
}
}
}
public static function inverseRoute($controller,$action) {
return ucfirst($controller)."@".$action;
}
public static function notFound($action,$method) {
die("Route not found:: $action with method $method");
}
}
我使用 json_decode 函数来解析 stdClass() 中的 json 对象.
I use the json_decode function to parse the json object in stdClass().
json 文件如下所示:
The json file looks like this:
{"routes":[
{"action":"Frontend@index", "method":"GET"},
{"action":"Frontend@register", "method":"GET"},
{"action":"Frontend@blog", "method":"GET"}
]}
这样我就可以将路由的方法列入白名单,并在未找到时返回 404 错误.
This way i can whitelist routes with their methods and return 404 errors while not found.
系统还是很基础的,但提供了想法和工作,希望有人会觉得有用.
System is still quite basic but gives and idea and works, hope someone will find useful.
相关文章