How to make cakePHP 2.x in sub directory appear in

2019-05-22 05:26发布

问题:

I'm working on an cake app which is inside a sub directory (because I need to run it along side another app on the same domain). I want the pages powered by cake to appear as if they'r e top level.

So instead of example.com/cake_dir/page... I want example.com/page...

I think the best way to make this work is by adding a rewrite rule to an .htaccess file, so here's what I want to know:

  1. Is this the best way to do this? If so:
  2. What is the proper syntax for that kind of rule?
  3. Where should that file go? The domain root? In the cake_dir? Or in cake's webroot?
  4. If one of Cake's .htaccess files already exists in that location, should the new rule go before or after and should and of the [L]s be removed?

UPDATE: Clearer description of what I'm trying to do

example.com/ <--root
    /_cake   <--CakePHP installed here
        /page3
        /page4

Currently, visitors have to access page 3 by going to example.com/_cake/page3. This sucks. Instead I want this: example.com/page3 and if cake routes to example.com/_cake/page4 I want it to appear as example.com/page4 in the browser.

I've been cramming as much mod_rewrite knowledge as possible and I think the way to do this is to do an internal rewrote to show the correct content when the _cake is absent, and an external rewrite for when _cake IS present.

Update Here are the existing .htaccess files...

.htaccess in /_cake...

<IfModule mod_rewrite.c>
   RewriteEngine on
   RewriteRule    ^$ app/webroot/    [L]
   RewriteRule    (.*) app/webroot/$1 [L]
</IfModule>

.htaccess in /_cake/app...

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

.htaccess in /_cake/app/webroot...

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    #RewriteRule ^(.*)$ index.php #[QSA,L]
    RewriteRule ^(.*)$ index.php [QSA]
</IfModule>

Update 2 I added anubhava's code to the root .htaccess file, and then also updated the .htaccess file at /_cake/ to look like the following (notice that I had to remove the [L]s in order for CakePHP's normal rewrites to still work):

# Turn mod_rewrite on
RewriteEngine On
RewriteBase /

# external redirect from /_cake/page to /page
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+_cake/([^\s]+) [NC]
RewriteRule ^ /%1 [R=302]

# internal forward from /page to /_cake/page
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (?!^_cake/)^(.*)$ /_cake/$1 [NC]


<IfModule mod_rewrite.c>
   RewriteEngine on
   RewriteRule    ^$ app/webroot/    [L]
   RewriteRule    (.*) app/webroot/$1 [L]
</IfModule>

回答1:

$DOCUMENT_ROOT/.htaccess:

Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /

# internal forward from /page to /_cake/page
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (?!^_cake/)^(.*)$ /_cake/$1 [L,NC]

$DOCUMENT_ROOT/_cake/.htaccess:

RewriteEngine on
RewriteBase /_cake/
RewriteRule (.*) app/webroot/$1 [L]

$DOCUMENT_ROOT/_cake/app/.htaccess:

RewriteEngine on
RewriteBase /_cake/app/
RewriteRule (.*) webroot/$1 [L]

$DOCUMENT_ROOT/_cake/app/webroot/.htaccess:

RewriteEngine On
RewriteBase /_cake/app/webroot/

RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+_cake/([^\s&]*) [NC]
RewriteRule ^ /%1 [R=302,L]

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


回答2:

If you want to make it so when someone requests http://example.com/page they actually get served the content provided by /cake_dir/page, then you should add these rules to the htaccess file in your document root (or "domain root"):

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/cake_dir%{REQUEST_URI} -f
RewriteRule ^(.*)$ /cake_dir/$1 [L]

The URL in the browser's address bar will remain unchanged because there is no external redirect. The condition here is that it checks if the %{DOCUMENT_ROOT}/cake_dir%{REQUEST_URI} points to a file. That string essentially puts together the document root, then the string "cake_dir", then the actual requested file. In the case that none of these requests actually point to physical files in the "cake_dir", you can try:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /cake_dir/$1 [L]

Here, the conditions are that the requested URI (e.g. /page) does not point to an existing file or directory. And it routes everything blindly into the /cake_dir directory.


To redirect the browser in the event that someone clicks on a link with cake_dir in it, then you need these rules:

RewriteCond %{THE_REQUEST} ^(GET|HEAD)\ /cake_dir/
RewriteRule ^cake_dir/(.*)$ /$1 [L,R=301]