如何从 Laravel URL 中删除 /public/

298

我想从我的Laravel 5网址中删除/public/片段。

我不想运行虚拟机,这在切换项目时似乎很尴尬。

我不想将我的文档根目录设置为public文件夹,这在切换项目时也很尴尬。

我尝试了使用.htaccess的mod_rewrite方法:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteRule ^(.*)$ public/$1 [L]
</IfModule>

但是这给了我一个Laravel NotFoundHttpException在compiled.php的7610行。

在Laravel 4中,我可以将public文件夹的内容移动到根目录。 Laravel 5的结构非常不同,按照相同的步骤完全破坏了Laravel(服务器只会返回一个空白页面)。

是否有一种方法可以在开发环境中删除“public”,以便我可以轻松地在项目之间切换(我通常同时处理2或3个项目)?

我正在使用MAMP和PHP 5.6.2


1
指南中的文件夹结构与我的不同,我想他没有使用L5?我省略了他对Bootstrap/Paths文件所做的更改,因为该文件不存在。项目似乎正在工作。你觉得这样可以吗? - user1537360
1
似乎只需修改index.php文件中的路径即可使其正常工作,但我对Laravel还很陌生,因此无法评论这是否稳定/安全。 - user1537360
4
这个页面上的大多数回答都是极其糟糕的做法。唯一安全的解决方案是将您的Web主机的_document root_更改为public文件夹。如果您正在使用只发布public_html文件夹的服务器,则删除此文件夹并创建一个新的public_html符号链接,指向并别名Laravel public文件夹。 - Snapey
2
一个public文件夹存在于文档根目录下,只用作公开访问,不应有其他文件存放其中。否则会导致私有存储、env文件和其他敏感文件面临安全风险。为了保证安全,请**更改您的文档根目录!**在本地环境之外没有任何合法原因不这么做,这就像是在数据库中不加密密码一样。 - Tofandel
显示剩余8条评论
37个回答

445

注意:这会引入非常重要的安全问题,不建议使用。

对于 Laravel 5:

  1. 将 Laravel 根目录中的 server.php 重命名为 index.php
  2. /public 目录中的 .htaccess 文件复制到 Laravel 根目录中。

23
请查看其他回答,这些回答只创建位于根目录中的 .htaccess 文件,因为此答案可能会暴露敏感信息(例如 .env 文件)。 - mauronet
15
您的网站易受黑客攻击,因为.env文件可以被任何人查看。 - Abd Abughazaleh
13
这并不安全。 - nassim
5
请继续向下滚动以获得更好的答案。 - Qumber
6
这个答案非常糟糕,很可能是 Laravel 网站被黑的头号原因。 - Private_GER
显示剩余5条评论

285


请注意,使用Docker服务Laravel项目时:您不需要执行任何操作。 仅在您的网站根目录(或更常见的是: public_html )目录是您的Laravel项目时使用此选项(当您使用Docker时不是这种情况)。

不要这样做!

您真的不应该将Laravel根文件夹中的server.php重命名为index.php并将/public目录中的.htaccess文件复制到Laravel根文件夹中!!!

这样每个人都可以访问您的一些文件(例如.env)。自己试试吧。您不想那样!


操作

相反,您应该在根目录中创建一个像这样的.htaccess文件:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/public/
RewriteRule ^(.*)$ /public/$1 [L,QSA]

这将悄悄地将所有基本URI重写为/public文件夹。甚至所有Headers,例如HTTP授权标头,以及所有可选的URI参数也将悄悄地传递到/public文件夹。


5
在生产环境中它运行正常,但在本地环境中无法运行,有何建议? - Haritsinh Gohil
4
这很完美!本地和服务器都感谢安全帮助! - Ghanshyam Nakiya
3
这个回答被低估了。因为加粗和突出了“不要”,我给它点了赞。它的效果非常好。 - Varun Ved
2
完美的答案 - Mansour Alnasser
2
@Tofandel 目标不是“将未公开的内容公开”,而是从 URL 中删除“/public/”。其中最简单且最常用的方法之一恰好是一种不安全的方式,人们往往会选择最简单/最常见的方法,因为他们不知道更好的方法。 - TylerH
显示剩余15条评论

140
注意:这会引入非常重要的安全问题,不建议使用。
我已经找到了两个解决方案来解决这个问题:
  1. 将server.php重命名为index.php(不进行修改)

  2. 将public文件夹中的.htaccess复制到根目录下(如rimon.ekjon所述)

  3. 对.htaccess进行以下静态资源的修改:

    RewriteEngine On
    
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ /$1 [L,R=301]
    
    RewriteCond %{REQUEST_URI} !(\.css|\.js|\.png|\.jpg|\.gif|robots\.txt)$ [NC]
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
    
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_URI} !^/public/
    RewriteRule ^(css|js|images)/(.*)$ public/$1/$2 [L,NC]
    
如果还需要其他的静态文件,只需将扩展名添加到先前声明的列表中。

1
这对我来说就像一记重拳! 它基本上解决了除主页外没有其他路由可用的问题,如果您尝试Derk的解决方案,那么它将起作用,但并非所有资产和图像都适用。 这个修复了路由,也修复了资产和图像。 非常感谢。 :) - Leutecia
3
恭喜!现在全世界都可以访问您的应用程序的配置文件。 - miken32

136
在Laravel 5.5中,需要在你的根目录下创建.htaccess文件,并放置以下代码:参考链接
<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} -d [OR]
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^ ^$1 [N]

    RewriteCond %{REQUEST_URI} (\.\w+$) [NC]
    RewriteRule ^(.*)$ public/$1 

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ server.php

</IfModule>

谢谢,这对我很有用。但我想知道它是否存在任何安全问题。 - rahul singh Chauhan
@rahulsinghChauhan 很高兴为您服务。亲爱的,我不知道安全问题,但应该是安全的。 - Raham
3
这条规则 RewriteRule ^ ^$1 [N] 做什么? (翻译:What does this rule RewriteRule ^ ^$1 [N] do?) - gonzo
1
在链接视图资源时,例如具有不起作用的admin.something.something的仪表板。任何修改都必须在路由文件中完成吗? - Luiz Wynne
1
@LuizWynne 看一下我的答案 - Derk Jan Speelman
1
只是想知道如何避免/public被识别为有效的URL。 - cdsaenz

54
在根目录下创建一个.htaccess文件,并放置以下类似的代码。然而,这仍然允许通过URL访问您的.env文件,因此不安全。
<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} -d [OR]
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^ ^$1 [N]

    RewriteCond %{REQUEST_URI} (\.\w+$) [NC]
    RewriteRule ^(.*)$ public/$1 

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ server.php
</IfModule>

3
我强烈推荐这个解决方案。 - TheLastCodeBender
1
我也推荐这个解决方案。 - eduardo a
4
运行良好,但仍然可以直接从URL访问.env文件。 - Manoj Singh
1
这是一个安全的解决方案吗? - Senior PHP Developer
我的代码似乎不能正常工作 :( - Ripon Uddin
显示剩余3条评论

45

简单的方法来从Laravel 5的URL中移除public。 您只需要将public目录下的index.php和.htaccess剪切并粘贴到根目录中,就这样。 然后在index.php文件中替换两行代码。

require __DIR__.'/bootstrap/autoload.php';
$app = require_once __DIR__.'/bootstrap/app.php';

注意:上述方法仅适用于初学者,因为他们可能在设置虚拟主机时遇到问题。最佳解决方案是在本地计算机上设置虚拟主机,并将其指向项目的公共目录。


1
之后CSS无法加载,因为所有的CSS都在公共文件夹中,而公共文件夹已从URL中删除。 - Mr. Tomar
2
在加载js或css文件时,您可以在前面加上“public/”,例如Html :: script(“public/js/.....”);
  • 但最好的解决方案是虚拟主机...
- Muhammad Sadiq

40

不建议使用此答案,因为它会编辑供应商提供的文件。相反,建议通过更改您的.htaccess文件来处理它。


rimon ekjon说:

将Laravel根目录中的server.php重命名为index.php,并将/public目录中的.htaccess文件复制到Laravel根目录。

这个方法是有效的,但当我进行这个更改后,/public目录中的所有资源文件都无法找到,并且请求URL也不起作用,因为我使用了asset()助手。

我修改了/Illuminate/Foundation/helpers.php/asset()函数如下:

function asset($path, $secure = null)
{
    return app('url')->asset("public/".$path, $secure);
}

现在一切都恢复正常了。


4
这不是解决问题的好方法,因为你正在尝试在供应商目录中进行更新,这不是一个好的做法。 - Shadman
1
您只需要将 RewriteRule ^(.*)$ public/$1 [L] 添加到您从 public 目录复制的 .htaccess 文件中,同时删除这行代码 RewriteRule ^(.*)/$ /$1 [L,R=301] - Shadman
Rimon Ekjon是谁?你在哪里看到他们说这句话的? - TylerH

35
只需在根目录创建.htaccess文件并添加以下行即可。
<IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteRule ^(.*)$ public/$1 [L]
</IfModule>

上述代码适用于根目录下的public_html文件夹。但是,您的核心Laravel文件应该在public_html文件夹内,如果您的目录看起来像public_html/laravelapp/public,并且如果您将上述代码放在laravelapp中,则它将无法正常工作。因此,您必须将所有核心文件复制到public_html中,并将.htaccess文件放在那里。

如果您想将代码保留在子目录中,则可以创建一个子域,然后此代码也将适用于该子域。


在阅读你的答案之前,我已经回答了下面的内容,并且这个答案必须被接受。没有文件更改:只需要一个简单、聪明的规则。 - Brigo
@Raham,你当前的URL是什么? - Abhinav Saraswat
2
只是想在这位先生的工作顶部添加一个简短的描述。上面的代码适用于根公共_html文件夹(我也遇到了问题)。话虽如此,你的核心laravel文件应该在public_html文件夹内,我犯了一个错误,我的目录看起来像public_html/laravelapp/public,如果你把上面的代码放在laravelapp里面,它不会起作用。因此,你必须将所有的核心文件复制到public_html中,并将.htaccess文件放在那里。参考centOS和Cpanel托管laravel。 - Deepesh Thapa
这是唯一一个提供简单解决方案的答案(当然,除了我的答案之外)。其他答案存在许多缺点,例如存储路径、资源路径和其他与URL/路径相关的问题。此外还存在重大安全漏洞,例如公开访问.env文件。 - Derk Jan Speelman
1
对我来说非常好用,我只有cPanel webshost,无法更改Apache的RootDirectory。谢谢!最简单和最安全的方法。这不会允许查看您的根文件夹内容。 - Vincent Decaux
显示剩余3条评论

23

1) 我还没有找到在 L5 中移动公共目录的可行方法。虽然你可以修改一些内容在引导文件 index.php 中,但好像有几个辅助函数是基于公共目录存在的假设进行的。实话说,你真的不应该移动公共目录。

2) 如果你使用 MAMP,那么你应该为每个项目创建新的虚拟主机,每个虚拟主机服务于该项目的公共目录。一旦创建,你可以通过定义的服务器名称访问每个项目,如下所示:

http://project1.dev
http://project2.dev

15

去除URL中的public的4种最佳方法。

如果您使用了其他技巧来删除URL中的public,例如将server.php的名称更改为index.php并更改为核心文件路径。请明确不要这样做。那么为什么Laravel不像这样提供解决方案,因为这不是一个适当的方法。

1)使用htaccess在Laravel中删除URL中的public

通过在根目录中添加.htaccess文件,您可以访问没有public的网站。

<ifmodule mod_rewrite.c>
    <ifmodule mod_negotiation.c>
        Options -MultiViews
    </ifmodule>

    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} -d [OR]
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^ ^$1 [N]

    RewriteCond %{REQUEST_URI} (\.\w+$) [NC]
    RewriteRule ^(.*)$ public/$1 

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ server.php

</ifmodule>

2) 通过在本地创建虚拟主机来删除公共

我这里演示的是 Windows 操作系统,但我将尝试定义一些步骤,以便任何人都可以轻松跟随。您也可以在谷歌上为特定的操作系统进行研究。

步骤1:转到 C:\Windows\system32\drivers\etc\,以管理员模式打开 "hosts" 文件。

步骤2:添加以下代码。在此,我为 projectname.local 域名提供演示,您可以随意指定任何域名,只需在每个位置都使用相同的名称即可。

127.0.0.1  projectname.local

步骤3:现在,对于xampp用户,请前往C:\xampp\apache\conf\extra,对于wamp用户,请前往"C:\wamp\bin\apache\Apache2.4.4\conf\extra"并打开"httpd-vhosts.conf"文件。现在在其中添加以下代码。

注:根据您的项目更改文档根目录,也将域名添加到“hosts”文件中定义。

<VirtualHost projectname.local>
      ServerAdmin projectname.local
      DocumentRoot "C:/xampp/htdocs/projectdir"
      ServerName projectname.local
      ErrorLog "logs/projectname.local.log"
      CustomLog "logs/projectname.local.log" common
 </VirtualHost>

步骤4:最后一个也是非常重要的一步,就是重新启动你的Xampp或Wamp,并通过http://projectname.local这个链接访问你的Laravel网站,这样就不需要加public URL了。


3)使用Laravel命令去掉public

如果您在本地工作,则无需做任何操作,只需从终端或命令行工具中运行以下命令即可。之后,您可以使用命令行提供的URL访问您的网站。

   > php artisan serve
如果您想在特定IP上运行项目,则需要运行以下命令。如果您正在本地局域网上工作,并且想要允许其他人从本地访问您的网站,则只需通过命令行运行“ipconfig”来检查您的IP地址,然后运行以下命令。
> php artisan serve --host=192.168.0.177
如果你想在特定的IP地址和端口上运行你的项目,那么你需要执行以下命令。
> php artisan serve --host=192.168.0.177 --port=77

4) 在托管服务器或cPanel上删除public文件夹

enter image description here

完成项目后,您需要将其托管在服务器上,然后只需将文档根目录设置为public文件夹。请参考下面的屏幕截图。

如果您在public_html中没有任何项目文件夹,则只需像"public_html/public"一样设置文档根目录。

参考此处


1
所有四种方法都不错,但我已经通过使用第一种解决方案来解决了我的问题。 - Manisha
@MayankDudakiya 如果一个 Laravel 6 应用程序没有加载 CSS JS,当您执行 Ctrl + U 时,您会看到这个 https://i.postimg.cc/R00GQkXQ/Untitled.jpg,您会怎么做? - Umair
根据您的截图,@Umair,您的路径中存在一个错误。它包含了/public//public。请尝试从您的asset()url()函数中删除/public/ - Mayank Dudakiya
@MayankDudakiya,这是因为我在.env文件中设置了ASSET_URL=public,但即使删除它,CSS和JS文件仍无法加载。网络选项卡显示404错误。我还尝试过{{ URL::asset('css/style.css') }}和{{ asset('css/style.css') }},并尝试使用不同的htaccess文件。还尝试从根目录中删除htaccess和index。权限也正确。我已经设置了许多Laravel应用程序,并遇到了这个问题,但我不知道该怎么办。所有文件都在那里,但无法加载。 - Umair
@Umair 我认为你应该遵循虚拟主机的方式,这是非常简单和方便的。如果你正在使用WAMP,那么设置将非常容易。你只需要右键单击WAMP图标,选择虚拟主机选项,然后添加路径和域名,例如 yourproject.localyourproject.dev - Mayank Dudakiya
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接