簡體   English   中英

用戶友好的URL - mod重寫和php重定向

[英]User friendly URLs - mod rewrite and php redirections

到目前為止我已經這樣做了:

RewriteBase /
RewriteCond  %{REQUEST_FILENAME} !-f
RewriteCond  %{REQUEST_FILENAME} !-d
RewriteRule  ^(.*)$ index.php?load=$1 [QSA,L]

然后在我的索引頁面(在根目錄中)我正在使用PHP來確定要加載的頁面:

// Swap to variables
    $load = $_GET['load'];

// Home page
    if (!$load || $load == "") { include('home.php'); exit(); }

// Dashboard
    if ($load == "dashboard") { include('dashboard.php'); exit(); }

// About
    if ($load == "about") { include('about.php'); exit(); }

// Username
    $data_array = array(':username' => $load);
    $select_account = $connect->prepare("SELECT * FROM `users` WHERE `username` = :username");
    $select_account-> execute($data_array);
    $account_amount = $select_account->rowCount();
    if ($account_amount > 0) { include('profile.php?name=$load'); exit(); }

// Redirect to 404 if there are no results
    include('404.php'); exit();

到目前為止一切正常,但用戶可以將照片上傳到圖庫,我希望他們可以像這樣查看:

www.mysite.com/[username]/gallery/

但是如果你打算將其作為網址輸入,則重寫將[username]/gallery/作為一個部分,這意味着$load = [username]/gallery這將給我一個'404'。

可能有一個更好的解決方案來獲得理想的結果,但我對.htaccess和重寫並不太好。 我想補充一點,我也喜歡這個重寫,因為我有一個名為signupsignin的子目錄,它們都有子目錄,但是如果我轉到URL:

www.mysite.com/signup
www.mysite.com/signin

它忽略了重寫並轉到目錄而不是通過$load語句運行它,這是我想要的。

另外,要注意,在注冊帳戶時,任何與字符串(如dashboardabout等)匹配的用戶名都不允許他們使用它,這會停止用戶名和$load if / else語句及其包含被混淆等

編輯

我忘記注意的另一件事是,因為他們可以隨意調用圖庫,它需要搜索以查看該圖庫是否存在,例如:

www.mysite.com/username/my+first+album

它首先需要檢查用戶名是否存在,然后檢查相冊是否存在,然后顯示它是否存在,如果不存在則顯示為404 /重定向到哪里。 所以基本上,兩個參數/查詢都是動態的。 不僅如此,那么該專輯​​中的單張照片需要同樣的工作,例如:

www.mysite.com/username/my+first+album/my+picture

我希望這是有道理的...

一個簡單的解決方案是:EDIT HTACCESS

RewriteBase /
RewriteCond %{REQUEST_URI}  !/signup
RewriteCond %{REQUEST_URI}  !/signin
RewriteRule ^([^/]*)/([^/]*)$ index.php?load=gallery&username=$1&gallery=$2
RewriteCond  %{REQUEST_FILENAME} !-f
RewriteCond  %{REQUEST_FILENAME} !-d
RewriteRule  ^(.*)$ index.php?load=$1 [QSA,L]

現在那個PHP部分(對於index.php):

$load = $_GET['load'];
switch ($load){
    default:
        include('home.php');
        exit();
    break;
    case 'dashboard':
        include('dashboard.php');
        exit();
    break;
    case 'about':
        include('about.php');
        exit();
    break;
    case 'gallery':
        $username = $_GET['username'];
        $gallery = $_GET['gallery'];

        //check for the username and gallery

        header("Location: your-gallery-location-goes-here");
    break;
}

希望它會有所幫助:)

您想要的是所謂的URL路由器,這需要您分析URL並根據內容做出決策。 大多數系統通過讓您提供url模板以及在url匹配時調用的函數來完成此操作。 該函數通常傳遞給模板URL中的任何子匹配。

例如,Django使用正則表達式作為其url路由,並將命名匹配作為參數傳遞給給定的函數(或類)。

如果這對您的需求來說過於復雜,那么您可以使用特定的正則表來解析網址,您的圖庫大小寫將是:

$matches = array();
$re = "/\/([\w\d])+\/([\w\d+%])+\/?/";
preg_match($re, $load, $matches);
$username = $matches[0];
$gallery  = $matches[1];

然后你可以使用$username$gallery

注意

以上假設它將匹配,您需要檢查preg_match的返回值以確保。 此外,我沒有檢查正則表達式,它可能是錯誤的,或使用不在此語法中的功能。

參考

這是一個簡單的例子:

的.htaccess

RewriteEngine On
RewriteRule ^includes/.*$ index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]

首先,您必須拒絕直接訪問.php文件,您可以將它們放在單獨的文件夾中,如'/ includes',並將對該文件夾的任何調用重定向到index.php。 其次,允許直接訪問文件(如圖像或javascripts)。 最后一條規則,將其他任何內容重定向到index.php。

PHP

基本上你必須有一組規則來測試URL和一些控制器來處理結果。

define( 'WEB_ROOT', rtrim( dirname($_SERVER["SCRIPT_NAME"]), '/' ) );
define( 'INCLUDES_ROOT', 'includes/' );

// examples of rewrite rules ( $key = action, $value = regular expression )
$rules = array( 
    'pages' => "/(?'page'dashboard|about|signin|signup)",   // e.g. '/about'
    'gallery' => "/(?'username'[\w\-]+)/gallery",   // e.g. '/some-user/gallery'
    'album' => "/(?'username'[\w\-]+)/(?'album'[\w\-]+)",   // e.g. '/some-user/some-album'
    'picture' => "/(?'username'[\w\-]+)/(?'album'[\w\-]+)/(?'picture'[\w\-]+)",     // e.g. '/some-user/some-album/some-picture'
    'home' => "/"   // e.g. '/'
    );

// get uri
$uri = '/' . trim( str_replace( WEB_ROOT, '', $_SERVER['REQUEST_URI'] ), '/' );

// test uri
foreach ( $rules as $action => $rule ) {
    $pattern = '/^'.str_replace( '/', '\/', $rule ).'$/';

    if ( preg_match( $pattern, $uri, $params ) ) {
        /* now you know the action and parameters so you can 
         * include appropriate template file ( or proceed in some other way )
         * NOTE: variable $params vill be visible in template ( use print_r( $params ) to see result )
         */
        include( INCLUDES_ROOT . $action . '.php' );
        // exit to avoid the 404 message 
        exit();
    }
}

// nothing is found so handle 404 error
include( INCLUDES_ROOT . '404.php' );

下一步是檢查收到的參數。

在Aatch和Sally的幫助以及URL路由的一些搜索結果的幫助下,我有了以下方法來實現我的目標,所以我想我會與所有人分享,以防任何人想要使用它...

首先,我需要提一下我正在處理的網站是在根文件夾mysite.com/sub/folder/index.php 2個子目錄中,因此為什么在數組上我從[3]開始

據說我的.htaccess文件如下:

RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . sub/folder/index.php [QSA,L]

這個,就我而言,獲取在sub/folder/之后編寫的任何內容,並將頁面直接重定向回index.php,但是,它會屏蔽地址欄中的URL。

它忽略這一點的唯一一次是子目錄實際存在。 所以例如我有一個文件夾/sub/folder/signup/如果我要在地址欄中鍵入它,因為目錄存在,那么你不會被重定向到index.php文件,而是發送到請求的目錄,就像正常一樣。

現在在我的index.php文件上(請記住我從$ uri開始[3],因為我在子文件夾中!)

$uri = $_SERVER['REQUEST_URI']; // This brings back /sub/folder/foo/bar/test/
$uri = explode("/", $uri); // Separate each one

$var_one = $uri[3]; // foo
$var_two = $uri[4]; // bar
$var_three = $uri[5]; // test

switch ($var_one) {

    case '':
    case 'home':
        include('home.php');
        exit();
        break;

    case 'signout':
    case 'logout':
        include('signout.php');
        exit();
        break;

    case 'dashboard':
    case 'dash':
        include('dashboard.php');
        exit();
    break;

}

// By Username
    $data_array = array(':username' => $var_one);
    $select_account = $connect->prepare("SELECT * FROM `users` WHERE `username` = :username");
    $select_account -> execute($data_array);
    $account_amount = $select_account->rowCount();
    if ($account_amount > 0) { include('profile.php'); exit(); }

// By Account ID
    $data_array = array(':id' => $var_one);
    $select_account = $connect->prepare("SELECT * FROM `users` WHERE `id` = :id");
    $select_account -> execute($data_array);
    $account_amount = $select_account->rowCount();
    if ($account_amount > 0) { include('profile.php'); exit(); }

include('page_not_found.php');

開關案例很簡單,如果url是:/ sub / folder / dashboard /則顯示dashboard.php。 如果沒有一個案例匹配,那么我們可能會查看個人資料。 第一個檢查是否可以是用戶名,如果存在,則顯示視圖配置文件頁面。 然后,它檢查它是否可能是該配置文件的唯一ID號並進行相同的檢查。

最后,如果沒有任何結果從它們中恢復,那么我們將顯示404頁面未找到的頁面。

如果它是個人資料頁面,在profile.php文件中,我可以運行$var_two檢查並查看他們是否已經以該名稱上傳了相冊,例如/sub/folder/joe/holiday/ if yes,然后運行查詢以獲取所有內容,如果沒有,則顯示消息/重定向或其他內容。

然后,如果還有更多,比如說該文件夾中的特定圖片( $var_three )( $var_two ),例如/sub/folder/joe/holiday/beach/ - 則通過顯示結果的類似查詢運行它。

它可能不是最好的方法,但它非常直接,一切都按照我的喜好工作,所以我不能抱怨。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM