iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 10
2

Why
我們昨天做了一個簡單的『單一入口的框架』但是網站連結都會變成

http://127.0.0.1/game/index.php?page=list

能不能變成乾淨的

http://127.0.0.1/game/list

可以!下面教你怎麼做到

How
首先我們需要確定網頁伺服器 Apache 的 rewrite 重寫路徑功能有啟動
如果不知道怎麼弄,這邊有教學傳送門:

https://stackoverflow.com/questions/869092/how-to-enable-mod-rewrite-for-apache-2-2

確認正常就可以補一個新檔案 .htaccee 做到我們想要的功能

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php [L]
</IfModule>

這是 index.php

<?php
session_start();
require('vendor/autoload.php'); // 載入 composer
require('route.php');   // 路由: 決定要去哪一頁,讀取該頁面需要的資料組合介面

這是 route.php 你會發現你需要 class Router, class Request 我補在下面

<?php
$route = new Router(Request::uri()); //搭配 .htaccess 排除資料夾名稱後解析 URL
$route->getParameter(1); // 從 http://127.0.0.1/game/aaa/bbb 取得 aaa 字串之意

// 用參數決定載入某頁並讀取需要的資料
switch($route->getParameter(1)){
    case "list":
      // 讀取全英雄列表資料
      // $DAO->query( ...略... );

      include('view/header/default.php'); // 載入共用的頁首
      include('view/body/list.php');
      include('view/footer/default.php'); // 載入共用的頁尾
    break;

    case "hero":
      // 讀取單一英雄資料
      // $DAO->query( ...略... );

      include('view/header/default.php'); // 載入共用的頁首
      include('view/body/hero.php');
      include('view/footer/default.php'); // 載入共用的頁尾
    break;

    default:
      include('view/header/default.php'); // 載入共用的頁首
      include('view/body/default.php');
      include('view/footer/default.php'); // 載入共用的頁尾
    break;
}

Request.php 這功能是把連結去掉可能多餘的資料夾名稱,也去掉連結後方問號的 GET 參數

<?php
class Request {
    public static function uri()
    {
        $uri = str_replace(static::getFolderName(), "", static::redirect_url());
        return trim($uri, '/');
    }

    private static function redirect_url() {
        if( isset($_SERVER['REDIRECT_URL']) )
            return $_SERVER['REDIRECT_URL'];
        return explode("?", $_SERVER['REQUEST_URI'] )[0];
    }

    private static function getFolderName()
    {
        $folder_name = str_replace("/index.php", "", $_SERVER['PHP_SELF']);
        return $folder_name;
    }
}

Router.php 功能是把 URL 轉解析成參數文字陣列,之後就可以用文字判斷我們要去哪裡

<?php
class Router {
    private $routes = [
        "^([a-zA-Z0-9-_]+)\/?$",
        "^([a-zA-Z0-9-_]+)\/([a-zA-Z0-9-_]+)\/?$",
        "^([a-zA-Z0-9-_]+)\/([a-zA-Z0-9-_]+)\/([a-zA-Z0-9-_]+)\/?$",
        "^([a-zA-Z0-9-_]+)\/([a-zA-Z0-9-_]+)\/([a-zA-Z0-9-_]+)\/([a-zA-Z0-9-_]+)\/?$"
    ];
    private $parameters = [];
    public function __construct($url) {
        foreach ($this->routes as $route) {
            if (!preg_match("/" . $route . "/", $url, $matches))
                continue;
            $this->parameters = array_slice($matches, 1);
        }
    }
    public function getParameter($index){
      if(isset($this->parameters[($index-1)])){
        return $this->parameters[($index-1)];
      }else{
        return "";
      }
    }
}

檔案放置的位置跟專案結構是這樣
https://ithelp.ithome.com.tw/upload/images/20171227/20107394aKLDTC0WtT.png

放新的檔案進入 libraries 後記得要下 composer 指令 重產檔案

composer dump

這樣就能用非常乾淨的 Clean URL 來開啟我們的小專案囉

http://127.0.0.1/game/

http://127.0.0.1/game/list

http://127.0.0.1/game/hero

https://ithelp.ithome.com.tw/upload/images/20171227/201073941fs4Tisl0D.png

https://ithelp.ithome.com.tw/upload/images/20171227/20107394ei0HAmVAUv.png


上一篇
Day 9. PHP教學: 從單一網頁到基礎框架概念
下一篇
Day 11. PHP教學: 使用單例模式來連接資料庫
系列文
寫給朋友的 PHP 從 0 到 100 實戰教程30

1 則留言

1
j2ian
iT邦新手 5 級 ‧ 2018-08-26 17:42:19

請問去除之後如果要傳遞GET參數是否就無法傳遞了?

我要留言

立即登入留言