Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 无法使相对路径、重写规则和路由按预期方式运行 背景_Php_Apache_Mod Rewrite_Url Rewriting_Routes - Fatal编程技术网

Php 无法使相对路径、重写规则和路由按预期方式运行 背景

Php 无法使相对路径、重写规则和路由按预期方式运行 背景,php,apache,mod-rewrite,url-rewriting,routes,Php,Apache,Mod Rewrite,Url Rewriting,Routes,我正在用PHP编写一个没有框架的web项目。我使用各种软件包以MVC模式编写。对于路由部分(我使用的),我必须在Apache服务器上设置一些重写规则,以使路由正常工作 该公司的服务器设置为所有应用程序代码都位于文档根目录之外,而alias用于在内部重定向到应用程序。这会在相对路径、路由和URL重写方面带来很多麻烦 我将把问题分解成几个步骤,试着一次理解一个步骤。如果您想了解我的整个问题,请参阅 第一部分 路由器将$\u SERVER[“REQUEST\u URI”]值与定义的路由进行比较,以确定

我正在用PHP编写一个没有框架的web项目。我使用各种软件包以MVC模式编写。对于路由部分(我使用的),我必须在Apache服务器上设置一些重写规则,以使路由正常工作

该公司的服务器设置为所有应用程序代码都位于文档根目录之外,而alias用于在内部重定向到应用程序。这会在相对路径、路由和URL重写方面带来很多麻烦

我将把问题分解成几个步骤,试着一次理解一个步骤。如果您想了解我的整个问题,请参阅

第一部分 路由器将
$\u SERVER[“REQUEST\u URI”]
值与定义的路由进行比较,以确定它映射到哪个操作。以下是路线:

$router->map("GET", "/", Hello1Controller::class);
$router->map("GET", "/hello2", Hello2Controller::class);
这是导航栏,只是用来演示路由:

<li><a href="/">Hello 1</a></li>
<li><a href="/hello2">Hello 2</a></li>
我有一个template.twig位于文档根目录(不在公共目录中)的外部,在template.twig中我尝试引用css文件:

<link href="css/style.css" type="text/css" rel="stylesheet"/>

请注意,请求的uri是
“/css/style.css”
,但在代码中我使用了相对路径
css/style.css
。这使我认为相对路径是相对于url中的当前“位置”的。不确定是在重写之前还是之后,但在本例中,结果是相同的——相对于根(因为uri的路径部分中没有任何内容)或index.php(与根位于同一目录中)。两者都导致了我们看到的
“/css/style.css”
,而不是
/usr/local/var/www/app/public/css/style.css

现在,如果在每个目录上下文中应用此重写规则,那么它将起作用:
%{REQUEST_FILENAME}
现在是附加到目录的相对路径,使其成为指向文件的完整路径

DocumentRoot "/usr/local/var/www/app/public"
<Directory "/usr/local/var/www/app/public">
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ /index.php [L]
</Directory>
问题:这只是重写规则中相对路径的默认行为吗?每个目录或.htaccess始终是它工作所必需的吗

这里还有我对相对路径的观察。如果我错了,请纠正我:

客户端代码中的相对路径(在html、css或细枝模板中,其中包含的资源在传递到客户端之前不会解析):

  • 如果引用具有相对路径的资源的文件位于文档根目录内,则相对路径直观地起作用:它是相对于当前文件的
  • 如果引用具有相对路径的资源的文件位于文档根之外(例如,在呈现并发送到客户端的模板文件中),则该路径与当前文件不相关。它是相对于当前url的。也就是说,“.”将返回url中的一个级别。这使我无法在这些文件中使用相对路径
第二部分 现在我更改了服务器设置,使文档根不再位于应用程序中,而是完全位于文档根中。我将应用程序/软链接到www/

DocumentRoot "/usr/local/var/www"
RewriteEngine On
RewriteRule ^/?$ /app/public/index.php [L]
<Directory "/usr/local/var/www/app/public">
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ /index.php [L]
</Directory>
甚至没有处理每个目录的定义。我尝试了重写规则的不同变体,包括添加和删除[L],更改两个重写规则的顺序,希望每个目录中的一个先执行,用自己的指令包装第一个重写规则,等等。。。这些都不起作用。 由于同样的原因,导航栏上的“hello 2”选项卡也无法正常工作–每个目录的重写规则根本没有处理

第三部分
下一步是将应用程序完全移出文档根目录,并使用alias在内部重定向到应用程序。

我为第2部分找到了一个解决方案:

    DocumentRoot "/usr/local/var/www"
    <Directory "/usr/local/var/www">
        RewriteEngine On
        RewriteRule ^$ app/public/ [L]
        RewriteRule (.*) app/public/$1 [L]
    </Directory>

    <Directory "/usr/local/var/www/app/public">
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^ index.php [L]
    </Directory>
DocumentRoot”/usr/local/var/www
重新启动发动机
重写规则^$app/public/[L]
重写规则(*)app/public/$1[L]
重新启动发动机
重写cond%{REQUEST_FILENAME}-F
重写cond%{REQUEST_FILENAME}-D
重写规则^index.php[L]
我们需要在根级别有一个每目录重写规则,以便在应用程序级别的每目录指令对其进行评估之前,将应用程序的路径附加到docroot

这并不是我读到的任何正式内容,而是我从实验中看到的东西:
uri的路径部分(在应用任何以前的重写规则之后)必须与“Directory”指令中指定的路径部分匹配,才能执行。因此,在开始时,我们位于文档根,因此每个目录指令的根级别执行。它将app/public部分附加在uri之前,因此现在uri路径包含指向app公共目录的整个路径。因此,可以执行应用程序的每个目录指令

第3部分可以通过添加别名以类似方式解决。 提供了一个例子



注:第2部分的实现没有实际意义,应在实际生产中避免。这只是我解决最终问题的中间步骤。只有您的公用文件夹(包含静态内容的文件夹)才应该位于文档根目录中。

欢迎使用Stackoverflow

看看你的答案,看起来你不需要按照你在答案中写的去做

如果您的项目位于:
/usr/local/var/www/app
您的文档根目录是:
/usr/local/var/www/app/public

看起来您对项目根文件夹和HTTP服务器
DocumentRoot
有点混淆

HTTP服务器
DocumentRoot
,是apache应该在根目录下处理的文件夹。i、 e.当您转到
http://myapp.com/index.php
,它将在
DocumentRoot
中查找
index.php

假设您已将站点配置为
VirtualHost
,与大多数人一样,您的vhost配置如下所示:

<VirtualHost *:80>
    ServerAdmin admin@myapp.local
    DocumentRoot "/usr/local/var/www/app/public"

    <Directory /usr/local/var/www/app>
        AllowOverride all
    </Directory>
    ServerName myapp.local

    ErrorLog "/var/log/myapp.local-error_log"
    CustomLog "/var/log/myapp.local-access_log" common
</VirtualHost>
您还应该在HTML中使用前面的斜杠
DocumentRoot "/usr/local/var/www"
RewriteEngine On
RewriteRule ^/?$ /app/public/index.php [L]
<Directory "/usr/local/var/www/app/public">
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ /index.php [L]
</Directory>
[rewrite:trace2] init rewrite engine with requested uri /css/style.css, referer: http://localhost/
[rewrite:trace3] applying pattern '^/?$' to uri '/css/style.css', referer: http://localhost/
[rewrite:trace1] pass through /css/style.css, referer: http://localhost/
[core:trace3] request authorized without authentication by access_checker_ex hook: /css/style.css, referer: http://localhost/
[core:info] AH00128: File does not exist: /usr/local/var/www/css/style.css, referer: http://localhost/
    DocumentRoot "/usr/local/var/www"
    <Directory "/usr/local/var/www">
        RewriteEngine On
        RewriteRule ^$ app/public/ [L]
        RewriteRule (.*) app/public/$1 [L]
    </Directory>

    <Directory "/usr/local/var/www/app/public">
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^ index.php [L]
    </Directory>
<VirtualHost *:80>
    ServerAdmin admin@myapp.local
    DocumentRoot "/usr/local/var/www/app/public"

    <Directory /usr/local/var/www/app>
        AllowOverride all
    </Directory>
    ServerName myapp.local

    ErrorLog "/var/log/myapp.local-error_log"
    CustomLog "/var/log/myapp.local-access_log" common
</VirtualHost>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /index.php$0 [PT]