我正在为php应用程序制作工具包.我已经制作了一个基于某些约定的路由系统,它运作良好,但是我想学习如何制作mod_rewrite规则或其他任何东西,以最终使该URL易于查看并对seo有益.
路由系统从设置应用程序和URL根目录的配置文件开始.
$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参数中创建controllers @ actions的实例controllers =?& action =?
这是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();
}
这样可以选择路由器必须呼叫的控制器和动作.
此处的路由器功能从根目录的settings.php获取APP URL.您将两个controllers @ action参数设置为im字符串,它使URL如下所示:
?的index.php控制器= X&安培;行动= Y&安培; [参数…]
<?php
需要’./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到action并传递GET / POST数据(从index.php收集,将它们作为数组放入方法签名中).
不要怪我使用全局POST / GET而不进行过滤,我还在开发东西,安全性东西将在之后制造;)
我想问一下,是否有人可以分享一些关于如何制作漂亮的网址(如网站/页面/动作)的想法.
例如www.site.com/blog/post?id=1
(实际上,路由器功能($query_data)中的N个参数以这种方式工作,您传递了array [‘id’=>’1’]并得到?id = 1)
制作良好网址的最佳策略是什么?
非常感谢,仍然在学习PHP.
如果有最好的方法可以做到这一点,请提供您的反馈.
解决方法:
我发现自己是问题的答案,我在这里发布也许有用.
我在根目录中添加了.htaccess文件:
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
这会将每个请求返回到root / index.php文件.
索引文件从HTTP请求收集路由,检查该路由是否存在于“ routes.json”文件中.
URL是这样写的:
site.com/controller/action. GET参数编写如下
site.com/controller/action/[params] / [value] ……此输出例如site.com/blog/post/id/1
对于REST也应该很好.
这里的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 \PlayPhp\Classes\Request();
// 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对象.
json文件如下所示:
{"routes":[
{"action":"Frontend@index", "method":"GET"},
{"action":"Frontend@register", "method":"GET"},
{"action":"Frontend@blog", "method":"GET"}
]}
这样,我可以用其方法将路由列入白名单,并在找不到时返回404错误.
系统还是很基本的,但是给出了想法并起作用,希望有人会发现有用.