简体   繁体   English

来自基本文件夹的绝对URL,带有重写

[英]Absolute URL from base folder with rewrite

I have a project running local on WampServer. 我有一个在WampServer上运行本地的项目。 It's an MVC-like structure; 这是一个类似MVC的结构; it rewrites the URL to index.php?url=$1 . 它将URL重写为index.php?url=$1 Full .htaccess : 完整.htaccess

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]

When I want to send the user to another page using PHP location: <location> it doesn't do this properly because of the rewriting (all-though I am technically always in index.php ). 当我想使用PHP location: <location>将用户发送到另一个页面时location: <location>由于重写而没有正确执行此操作(尽管我在技术上总是在index.php )。

For example if I am on http://localhost/project_name/controller/method/ and this controller's constructor or method tries to send me to: 例如,如果我在http://localhost/project_name/controller/method/并且此控制器的构造函数或方法尝试将我发送到:

  • header('location: another_controller/method'); sends me to http://localhost/project_name/controller/method/another_controller/method/ 发送给我http://localhost/project_name/controller/method/another_controller/method/
  • header('location: /another_controller/method'); sends me to http://localhost/another_controller/method/ 发送给我http://localhost/another_controller/method/

But I want it to send me like this: 但我希望它像这样发送给我:

  • header('location: /another_controller/method'); sends me to http://localhost/project_name/another_controller/method/ 发送给我http://localhost/project_name/another_controller/method/

Now the only solution I have found is: 现在我找到的唯一解决方案是:

define('BASE_URL','http://localhost/project_name');
header('location: '.BASE_URL.'/another_controller/method/');

But this isn't perfect either because it causes me to have to change this defined constant BASE_URL whenever the domain or folder name changes. 但这并不完美,因为只要域名或文件夹名称发生变化,我就必须更改此定义的常量BASE_URL I could also create a method in my BaseController that creates absolute URLs, but this method would basically just prepend BASE_URL too. 我也可以在我的BaseController中创建一个创建绝对URL的方法,但是这个方法基本上也只是前缀BASE_URL

Note: The same problem doesn't arise with HTML's src and href attributes, which can use relative paths (without project_name folder in path). 注意: HTML的srchref属性不会出现同样的问题,它们可以使用相对路径(路径中没有project_name文件夹)。 I don't understand why however. 但是,我不明白为什么。 Because if the header location causes the browser to append the the relative-URL to the current location, why doesn't it have the same behavior when looking for .css or .js files. 因为如果标头location导致浏览器将相对URL附加到当前位置,为什么在查找.css.js文件时它没有相同的行为。

So... this raises a couple of questions for me: 所以......这为我提出了几个问题:

  1. Would I have this problem if I had virtual hosts? 如果我有虚拟主机,我会遇到这个问题吗?
  2. What is the best way to solve this problem? 解决这个问题的最佳方法是什么?
  3. Is is best to just have the full absolute URL? 最好只拥有完整的绝对URL?
  4. Why do HTML's src and href attributes not share this behavior? 为什么HTML的srchref属性不共享此行为?

Now the only solution I have found is: 现在我找到的唯一解决方案是:

 define('BASE_URL','http://localhost/project_name'); header('location: '.BASE_URL.'/another_controller/method/'); 

But this isn't perfect either because it causes me to have to change this defined constant BASE_URL whenever the domain or folder name changes. 但这并不完美,因为只要域名或文件夹名称发生变化,我就必须更改此定义的常量BASE_URL。

You shouldn't need to change the defined constant. 您不需要更改定义的常量。 These values can be found dynamically. 可以动态找到这些值。

Example: 例:

if ($_SERVER['DOCUMENT_ROOT'] == dirname($_SERVER['SCRIPT_FILENAME'])) {
    define('BASE_PATH', '/');
} else {
    define('BASE_PATH', dirname($_SERVER['SCRIPT_NAME']) . '/');
}

$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
define('BASE_URL', $protocol . $_SERVER['SERVER_NAME'] . BASE_PATH);

Additionally, rather than worrying about whether to specify an absolute URL or a path, you can wrap the redirect into a function which can handle both: 此外,您可以将重定向包装到可以同时处理两者的函数中,而不是担心是指定绝对URL还是路径。

function redirect($path = null) {
    if (isset($path)) {
        if (filter_var($path, FILTER_VALIDATE_URL)) {
            header('Location: ' . $path);
        } else {
            header('Location: ' . BASE_URL . $path);
        }
    } else {
        header('Location: ' . BASE_URL);
    }
    exit;
}

Finally, as @HarshSanghani mentioned in the comments, the base path in your .htaccess file should match the base path in your code. 最后,正如@HarshSanghani在评论中提到的, .htaccess文件中的基本路径应该与代码中的基本路径匹配。 So if BASE_PATH (based on the example above) outputs /project_name/ , then your .htaccess should accommodate it: 因此,如果BASE_PATH (基于上面的示例)输出/project_name/ ,那么您的.htaccess应该适应它:

RewriteBase /project_name/

To answer your questions: 回答你的问题:

  1. It depends on how your virtual hosts would be configured. 这取决于您的虚拟主机的配置方式。
  2. You could simply generate your BASE_URL dynamically: $baseUrl = dirname($_SERVER['SCRIPT_NAME']); 你可以简单地动态生成你的BASE_URL: $baseUrl = dirname($_SERVER['SCRIPT_NAME']); . This way you won't have to change any code if your folder or domain changes. 这样,如果您的文件夹或域发生更改,则无需更改任何代码。
  3. You don't need the domain part. 您不需要域部分。
  4. The html src and href are interpreted by your browser which takes into account the page's <base> tag. html srchref由您的浏览器解释,它考虑了页面的<base>标记。 All paths on a page with a <base> tag get changed accordingly by your browser. 带有<base>标记的页面上的所有路径都会相应地由您的浏览器更改。

The HTTP headers you send from your server (for redirect) have nothing to do with the html page you send and are therefore not updated. 您从服务器发送的HTTP标头(用于重定向)与您发送的html页面无关,因此不会更新。

  1. You're going to have this problem if you have your project set up in a subdirectory. 如果您在子目录中设置了项目,则会遇到此问题。 Using virtual hosts would be a way round the issue if you wanted to set them up at say, project_name.localhost. 如果要在project_name.localhost中设置它们,则使用虚拟主机可以解决问题。
  2. In my projects I use an environment variable to load a different config file for development, staging or production. 在我的项目中,我使用环境变量来加载不同的配置文件以进行开发,登台或生产。 In this I set a $baseUri somehow. 在这个我设置一个$baseUri不知何故。
  3. It's best practice to use the absolute urls (including the domain) for both the solution of this problem and for SEO. 对于此问题的解决方案和SEO,最好使用绝对URL(包括域)。 In terms of functionality you don't need the domain part. 在功能方面,您不需要域部分。
  4. The src and href tags generally work the same way, but as Andreas mentioned they could be affected by the base tag. src和href标签通常以相同的方式工作,但正如Andreas所说,它们可能会受到基本标签的影响。

You should specify RewriteBase in your htaccess file. 您应该在htaccess文件中指定RewriteBase。 Use relative paths in your links and you need nothing more. 在链接中使用相对路径,您不需要任何其他路径。

RewriteBase /project_name/
RewriteEngine on
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM