【问题标题】:foo.com/alice vs. foo.com/users/alicefoo.com/alice 与 foo.com/users/alice
【发布时间】:2010-10-21 06:53:14
【问题描述】:

在您的网站上为用户的内容提供友好的 URL 固然很好。但如何最好地做到这一点?像 foo.com/users/alice 这样的东西有很多优点,最重要的是你不会弄乱你的根命名空间。但我认为用户的简单性胜过这一切。很多大网站似乎都同意(friendfeed、delicious 和 flickr 浮现在脑海中),这个问题是关于如何在服务器端实现这一点。

假设 alice 的真实 URL 是 foo.com/userpage?user=alice,如果有人试图浏览一个不存在的用户页面(比如 foo.com/bob),他们应该访问 foo.com/createnew?用户=鲍勃。

用户当然不应该看到上面那些丑陋的“真实”网址,只是 foo.com/alice 或 foo.com/bob。请注意,根命名空间是共享的。例如,foo.com/help 不应翻译为 foo.com/userpage?user=help。

大概我要求一些简单的 mod_rewrite 规则,但也许有一些我没有想到的完全不同的方法。无论如何,我认为最好为这个常见问题记录一个明确的或“最佳实践”的解决方案。

PS:请随意评论其他替代方案的优点,例如 alice.foo.com 或 users.foo.com/alice。

PPS:我想我在其他问题中看到过这个问题,但搜索起来似乎很棘手。欢迎指点!当然,还有其他关键字可以使其更易于搜索。关键字:用户空间、全局命名空间、URL 命名空间。

【问题讨论】:

    标签: url mod-rewrite url-rewriting namespaces friendly-url


    【解决方案1】:

    以下规则将 foo.com/bar 形式的 URL 重写为 foo.com/userpage?user=bar,条件是 bar 还不是服务器上的文件或目录。将以下内容放入 .htaccess 中:

    <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^([^/]+)/?$ userpage?user=$1 [NC,L]
    </IfModule>
    

    正如 Alex 的回答,如果用户不存在,用户页面脚本应该重定向到 createnew:

    $user = $_GET['user'];
    if (!user_exists($user)) {
      header('Location: createnew?user=' . urlencode($user));
    }
    

    (正如 Knuth 所说,请注意上述代码中的错误——我只是证明它是正确的,没有尝试过。当我真正确认它有效时,我会更新这个答案。) PS:确认!

    【讨论】:

    • 希望它有效!请记住,您必须编写一个 user_exists() 函数!
    【解决方案2】:

    我会说这取决于您的网站如何以用户为中心。

    像 myspace 这样的网站是http://www.myspace.com/jim/,因为该网站完全以用户为中心。

    但是,您可以注册但不重要或不强制的博客或新闻网站可以从中受益

    http://www.news.com.au/users/jim/

    你认为如果你正在做一个有用户的网站,你是否可以从 MVC 设计模式中受益,或者至少是一个使用路由器来引导 URI 的流行 MVC 框架?

    如果该 URI 来自路由器,然后被发送到 UsersController,您可以决定要么显示用户的个人资料,要么指示他们创建该用户。除了制定一条规则,将所有对不存在文件的请求定向到 index.php(或服务器端语言的默认值)之外,您不需要搞乱 mod_rewrite

    如果你确实想使用 mod_rewrite,试试这些规则

    RewriteEngine On
    RewriteCond %{REQUEST_URI} !(home|contact|about) [NC] // this line may be incorrect
    RewriteRule ^/users/([^/]+)/?$ userpage?user=$1 [NC,L]
    

    请注意 Gumbo 建议的前导克拉,因此它仅匹配 TLD 的 /users/。

    这将匹配 foo.com/users/bob 之类的任何内容,并带有可选的尾随斜杠。它不区分大小写,将是最后应用的规则。

    如果请求进入并且您的数据库中不存在 $_GET['user'],您可以尝试这样的操作

    $user = $_GET['user'];
    
    if (!user_exists($user)) {
    
        header('Location: createnew?user=' . urlencode($user));
        exit();
    
    }
    

    然后在 createnew 页面上,简单地做这样的事情

    <input type="text" name="username" value="<?php echo htmlspecialchars(urldecode($_GET['user'])); ?>" />
    

    这将使用他们尝试访问个人资料时使用的用户名自动填写用户名。

    如果您想了解更多关于 PHP 和 MVC 的信息,请尝试 Google 搜索或在 Stack Overflow 上提问。

    【讨论】:

    • 谢谢,很有帮助!关于 MVC 的要点。现在这只是 php,所以 mod_rewrite 规则在短期内会很有帮助。从长远来看,我认为您的建议是一种更好的方法。
    • 好的,我看看我能对 mod_rewrite 规则做些什么
    • 如果你想让所有 foo.com/alice 进入用户页面,你要么需要指定什么不应该去那里(比如 about|contact|help),要么你需要使用假的子目录,例如 /users/
    • 指定什么不应该去那里可能会成为一个维护问题,所以除非你致力于你的'hacked up php',否则 MVC 解决方案可能是最好的。我只是自己学习它,发现它很棘手/令人沮丧)。
    • 我想象我在服务器上有(嗯,事实上我确实有)文件或目录(或以前的 mod_rewrite 规则)用于所有不应该翻译的东西(比如 about|contact|帮助)。所以棘手的维护问题是确保你永远不会在服务器上创建 foo.com/bar 如果 bar 已经是用户名。
    猜你喜欢
    • 1970-01-01
    • 2010-10-24
    • 1970-01-01
    • 2018-10-20
    • 2017-11-30
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    相关资源
    最近更新 更多