Laravel 5 – Remove Public from URL

后端 未结 30 2382
甜味超标
甜味超标 2020-11-22 03:20

I know this is a very popular question but I haven\'t been able to find a working solution for Laravel 5. I\'ve been trying to migrate from Codeigniter for a long time, but

30条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-11-22 03:45

    Laravel 5.5

    After having installed Laravel for the first time, I faced the renowned "public folder problem" and I came up with this solution that, in my personal opinion, is "cleaner" then the others I found on the Web.


    Achievements

    • Don't have public word in the URI
    • Protect the .env file against curious people

    Everything can be done just editing the .htaccess using mod_rewrite and four simple rules.


    Steps

    1. Move the .htaccess file in public/.htaccess in the main root
    2. Edit it as below

    I commented everything, so it should be clear (I hope) also to those who have never used mod_rewrite (not that I'm an expert, all the opposite). Also, to understand the rules, it must be clear that, in Laravel, if Bill connects to https://example.com, https://example.com/index.php is loaded. This file just contains the command header("refresh: 5; https://example.com/public/"), which sends the request to https://example.com/public/index.php. This second index.php is responsible to load the controller and other stuff.

    # IfModule prevents the server error if the app is moved in an environment which doesn’t support mod_rewrite
    
        
            Options -MultiViews
        
    
        RewriteEngine On
    
        # RULES ORIGINALLY IN public/.htaccess ---
        # Redirect Trailing Slashes If Not A Folder...
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_URI} (.+)/$
        RewriteRule ^ %1 [L,R=301]
    
        # Handle Front Controller...
    #    RewriteCond %{REQUEST_FILENAME} !-d
    #    RewriteCond %{REQUEST_FILENAME} !-f
    #    RewriteRule ^ index.php [L]
    
        # Handle Authorization Header
        RewriteCond %{HTTP:Authorization} .
        RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
        # --- END
    
        # PERSONAL RULES ---
        # All the requests on port 80 are redirected on HTTPS
        RewriteCond %{SERVER_PORT} ^80$
        RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
    
        # When .env file is requested, server redirects to 404
        RewriteRule ^\.env$ - [R=404,L,NC]
    
        # If the REQUEST_URI is empty (means: http://example.com), it loads /public/index.php
        # N.B.: REQUEST_URI is *never* actually empty, it contains a slash that must be set as match as below
        # .* means: anything can go here at least 0 times (= accepts any sequence of characters, including an empty string)
        RewriteCond %{REQUEST_URI} ^/$
        RewriteRule ^(.*) /public/index.php [L]
    
        # If the current request is asking for a REQUEST_FILENAME that:
        # a) !== existent directory
        # b) !== existent file
        # => if URI !== css||js||images/whatever => server loads /public/index.php, which is responsible to load the app and the related controller
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule !^(css|js|images|media)/(.*)$ /public/index.php [L,NC]
    
        # If the current request is asking for a REQUEST_FILENAME that:
        # a) !== existent directory
        # b) !== existent file
        # => if URI == css||js||images[=$1]/whatever[=$2] => server loads the resource at public/$1/$2
        # If R flag is added, the server not only loads the resource at public/$1/$2 but redirects to it
        # e.g.: bamboo.jpg resides in example.com/public/media/bamboo.jpg
        #       Client asks for example.com/media/bamboo.jpg
        #       Without R flag: the URI remains example.com/media/bamboo.jpg and loads the image
        #       With R flag: the server redirects the client to example.com/public/media/bamboo.jpg and loads the image
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^(css|js|images|media)/(.*)$ /public/$1/$2 [L,NC]
        # --- END
    
    
    

    The following rule (originally in public/.htaccess) can be deleted. The same rule, in fact, is explicited in a more detailed way in the last two rules.

    # Handle Front Controller...
    #    RewriteCond %{REQUEST_FILENAME} !-d
    #    RewriteCond %{REQUEST_FILENAME} !-f
    #    RewriteRule ^ index.php [L]
    

    EDIT: I missed Abhinav Saraswat's solution and his answer should be the accepted one. Just one, simple and clear rule that redirects all the traffic to the public folder without modifying any file.

提交回复
热议问题