PHP-如何从路由器制作漂亮的重写URL

我正在为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错误.

系统还是很基本的,但是给出了想法并起作用,希望有人会发现有用.

上一篇:性能-其他解决方案,而不是NGINX的.htaccess


下一篇:Zookeeper之zkCli.sh客户端的使用