【问题标题】:how to make nice rewrited urls from a router如何从路由器制作漂亮的重写网址
【发布时间】:2016-01-05 07:46:18
【问题描述】:

我正在为 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 开始,这使得 controllers@actions 的实例来自 GET 参数 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();
    }

这允许选择路由器必须调用的控制器和操作。

这里的router函数从root的settings.php中获取APP URL。您将两个 controllers@action 参数作为字符串提供给我,它使 URL 如下所示: index.php?controller=X&action=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 到操作并传递 GET/POST 数据(从 index.php 收集,将它们作为数组放入方法签名中)。

不要怪我在没有过滤的情况下使用全局 POST/GET,我还在开发这个东西,以后会做安全的事情;)

我想问一下是否有人可以分享一些关于如何制作漂亮的网址(如网站/页面/操作)的想法...... 例如 www.site.com/blog/post?id=1

(实际上路由器函数 ($query_data) 中的 N 个参数是这样工作的,你传递 array['id' => '1'] 得到 ?id=1)

制作好网址的最佳策略是什么? 非常感谢,还在学习PHP。

如果有最好的方法来做这些事情,请提供您的反馈。

【问题讨论】:

    标签: php .htaccess mod-rewrite url-rewriting url-routing


    【解决方案1】:

    我找到了问题的答案,我在这里发帖也许有用。

    我在根目录中添加了一个 .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 错误。

    系统仍然很基本,但给出了想法和工作,希望有人会觉得有用。

    【讨论】:

      猜你喜欢
      • 2012-08-29
      • 2011-10-03
      • 2014-09-11
      • 2016-12-24
      • 2017-01-16
      • 2015-11-24
      • 2013-05-20
      • 2019-09-11
      • 2010-10-29
      相关资源
      最近更新 更多