Chuyển hướng tất cả sang index.php bằng htaccess


130

Tôi đang viết một khung công tác MVC-ish dựa trên PHP đơn giản. Tôi muốn khung này có thể được cài đặt trong bất kỳ thư mục nào.

Kịch bản PHP của tôi lấy uri yêu cầu và chia nó thành các phân đoạn. Nó làm cho phân đoạn 1 trở thành bộ điều khiển và phân khúc 2 là hành động. Điều này sẽ ổn khi tôi làm điều này:

http://www.example.com/mvc/module/test/

Nó sẽ đi đến bộ điều khiển mô-đun cụ thể và phương pháp. Bây giờ tôi có một bộ điều khiển mặc định, bộ điều khiển gia đình, trong thư mục home.

Bây giờ khi tôi truy cập trực tiếp vào thư mục này http://www.example.com/mvc/home/ Nó sẽ hiển thị 403 bị cấm, vì thư mục này tồn tại, thay vào đó, nó cũng nên quay lại http://www.example.com /mvc/index.php

Nếu tôi đã cài đặt khung trong một thư mục khác, giả sử khung thư mục đó phải chuyển hướng trở lại http://www.example.com/framework/index.php

Tôi muốn chuyển hướng mọi thư mục và tập tin php trở lại tệp index.php, để mọi thứ khác như vậy.

Vấn đề đầu tiên tôi gặp phải là nó không bao giờ chuyển hướng đến đúng thư mục, luôn luôn đến thư mục gốc tên miền.

Đây là những gì tôi đã cố gắng:

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

Chỉ để đảm bảo tôi hiểu chính xác câu hỏi của bạn: bạn muốn chuyển hướng mọi yêu cầu đến thư mục gốc index.php hoặc bạn muốn chuyển hướng mọi yêu cầu được thực hiện đến thư mục cụ thể đó index.php ?
Technoh

Đối với thư mục tập tin htaccess nằm trong thư mục gốc của khung. Trong ví dụ của tôi trở lại thư mục mvc
David Ericsson

Câu trả lời:


258

Quy tắc viết lại của bạn trông gần như ok.

Trước tiên, hãy đảm bảo rằng .htaccesstệp của bạn nằm trong thư mục gốc của tài liệu (cùng địa điểm index.php) hoặc nó sẽ chỉ ảnh hưởng đến thư mục con trong đó (và bất kỳ thư mục con nào trong đó - theo cách đệ quy).

Tiếp theo thực hiện một thay đổi nhỏ cho quy tắc của bạn để nó trông giống như:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]

Tại thời điểm bạn chỉ cần phù hợp trên .đó là một thể hiện của bất kỳ nhân vật, bạn cần ít nhất .*để phù hợp với bất kỳ số lượng các trường hợp bất kỳ ký tự.

Các $_GET['path']biến sẽ chứa các cấu trúc thư mục giả, vì vậy /mvc/module/teství dụ, sau đó bạn có thể sử dụng trong index.php để xác định điều khiển và hành động mà bạn muốn thực hiện.


Nếu bạn muốn toàn bộ shebang được cài đặt trong một thư mục con, chẳng hạn như /mvc/hoặc /framework/cách ít phức tạp nhất để làm điều đó là thay đổi quy tắc viết lại một chút để tính đến điều đó.

RewriteRule ^(.*)$ /mvc/index.php?path=$1 [NC,L,QSA]

Và đảm bảo rằng bạn index.phpđang ở trong thư mục đó trong khi .htaccesstệp nằm trong thư mục gốc.


Thay thế cho$_GET['path'] (cập nhật 18 tháng 2 và 19 tháng 1)

Thực sự không cần thiết (thậm chí không phổ biến bây giờ) để đặt đường dẫn làm $_GETbiến, nhiều khung sẽ dựa vào $_SERVER['REQUEST_URI']để truy xuất cùng một thông tin - thông thường để xác định Bộ điều khiển nào sẽ sử dụng - nhưng nguyên tắc hoàn toàn giống nhau.

Điều này không đơn giản hóa RewriteRulemột chút vì bạn không cần tạo tham số đường dẫn (có nghĩa là bản gốc của OP RewriteRule sẽ hoạt động):

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [L,QSA]

Tuy nhiên , quy tắc về cài đặt trong thư mục con vẫn được áp dụng, ví dụ:

RewriteRule ^.*$ /mvc/index.php [L,QSA]



Cờ:

NC = Không có trường hợp (không phân biệt chữ hoa chữ thường, không thực sự cần thiết vì không có ký tự nào trong mẫu)

L = Lần cuối (nó sẽ dừng viết lại sau phần Viết lại này để đảm bảo đó là điều cuối cùng trong danh sách viết lại của bạn)

QSA= Nối chuỗi truy vấn, chỉ trong trường hợp bạn có một cái gì đó giống như ?like=penguinsở cuối mà bạn muốn giữ và chuyển đến index.php.


1
nó phải là index.php? path = $ 1
Jacek Pietal

1
@Prozi không phải nếu bạn đang ở trong một thư mục con và index.php nằm trong docroot, thì bạn cần hàng đầu / - với Options +Indexesindex.php trong DirectoryIndexbạn có thể bỏ hoàn toàn index.php và chỉ sử dụng /?path=$1Điều này đúng khi thực hiện viết lại thông qua .htaccess chứ không phải trong một lệnh loại httpd-vhosts.conf <Directory>.
CD001

Nếu bạn sử dụng và dựa vào $ _GET ['path'], bạn sẽ gặp rắc rối trong trường hợp chuyển sang máy chủ nginx ...
barell

3
Bài đăng hay! Đáng lưu ý người dùng có thể ghi đè $_GET['path']nếu họ thêm path=whatevervào URL.
rybo111

1
@Liviuge - đúng, nhưng ban đầu tôi đã đi qua toàn bộ con đường để $_GETnó sẽ yêu cầu (.*)... thật buồn cười nhưng RewriteRule mà OP đã sử dụng 6 năm trước không hoạt động với họ - nhưng với cách kiến ​​trúc MVC có đã phát triển với PHP (như tôi đã đưa vào Bản cập nhật ngày 18 tháng 2 ) bây giờ ... đoán họ đã đi trước thời đại :) Vẫn cần đường dẫn chính xác đến /mvc/thư mục.
CD001

28

Để chuyển hướng tất cả mọi thứ mà doesnt tồn tại đến index.php, bạn cũng có thể sử dụng các FallBackResourcechỉ thị

FallbackResource /index.php

Nó hoạt động tương tự như ErrorDocument, khi bạn yêu cầu một đường dẫn hoặc tệp không tồn tại trên máy chủ, lệnh sẽ âm thầm từ chối yêu cầu index.php.

Nếu bạn muốn chuyển hướng mọi thứ ( including existant files or folders) đến index.php, bạn có thể sử dụng một cái gì đó như sau:

RewriteEngine on

RewriteRule ^((?!index\.php).+)$ /index.php [L]

Lưu ý mẫu ^((?!index\.php).+)$ phù hợp với bất kỳ uri nào ngoại trừ index.phpchúng tôi đã loại trừ đường dẫn đích để ngăn lỗi lặp vô hạn.


Nhưng bạn cũng có thể muốn sử dụng:DirectoryIndex index.php
Shao

1
Sử dụng *thay vì +trong mẫu nếu bạn cũng muốn chuyển hướng đường dẫn gốc.
Mir-Ismaili

15

Bạn có thể sử dụng một cái gì đó như thế này:

RewriteEngine on
RewriteRule ^.+$ /index.php [L]

Điều này sẽ chuyển hướng mọi truy vấn đến index.php của thư mục gốc. Lưu ý rằng nó cũng sẽ chuyển hướng truy vấn cho các tệp tồn tại, chẳng hạn như hình ảnh, tệp javascript hoặc biểu định kiểu.


1
Giải pháp này gần như làm việc cho tôi. Tôi tiếp tục nhận được "AH00124: Yêu cầu vượt quá giới hạn 10 lần chuyển hướng nội bộ". Tôi đã thêm "RewriteRule ^ index \ .php - [L]" trước đây và nó hoạt động hoàn hảo!
Fredster

11

Có một "mẹo" cho vấn đề này phù hợp với tất cả các kịch bản, một giải pháp rõ ràng đến mức bạn sẽ phải thử để tin rằng nó thực sự hoạt động ... :)

Đây là ...

<IfModule mod_rewrite.c>

   RewriteEngine On

   RewriteCond %{REQUEST_FILENAME}  -f [OR]
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteRule ^(.*)$ index.php [L,QSA]

</IfModule>

Về cơ bản, bạn đang yêu cầu MOD_REWRITE luôn chuyển tiếp đến index.phpyêu cầu URI khi tệp tồn tạiluôn luôn khi tệp được yêu cầu không tồn tại !

Khi điều tra mã nguồn của MOD-REWRITE để hiểu cách thức hoạt động của nó, tôi nhận ra rằng tất cả các kiểm tra của nó luôn xảy ra sau khi xác minh nếu tệp tham chiếu có tồn tại hay không. Chỉ sau đó RegExđược xử lý. Ngay cả khi URI của bạn trỏ đến một thư mục, Apache sẽ thực thi kiểm tra các tệp chỉ mục được liệt kê trong tệp cấu hình của nó.

Dựa trên khám phá đơn giản đó, rõ ràng việc xác thực tệp đơn giản sẽ đủ cho tất cả các cuộc gọi có thể , miễn là chúng ta nhấn đúp vào kiểm tra hiện diện tệp và định tuyến cả hai kết quả đến cùng một điểm cuối, bao gồm 100% khả năng.

QUAN TRỌNG: Lưu ý rằng không có " / " trong index.php. Theo mặc định, MOD_REWRITE sẽ sử dụng thư mục được đặt làm "thư mục cơ sở" để chuyển tiếp. Cái hay của nó là không nhất thiết phải là "thư mục gốc" của trang web, cho phép giải pháp này hoạt động localhost/và / hoặc bất kỳ thư mục con nào bạn áp dụng.

Cuối cùng, một số giải pháp khác mà tôi đã thử nghiệm trước đây (những giải pháp có vẻ hoạt động tốt) đã phá vỡ khả năng PHP "yêu cầu" một tệp thông qua đường dẫn tương đối của nó, đó là một lỗi. Hãy cẩn thận.

Một số người có thể nói đây là một giải pháp không phù hợp. Thực tế có thể, nhưng theo như các thử nghiệm, trong một số tình huống, một số máy chủ, một số phiên bản Apache khác nhau, v.v., giải pháp này đã hoạt động 100% trong mọi trường hợp!


Cảm ơn, điều này đã khắc phục sự cố của tôi, theo đó một FallbackResource index.phpdòng hoạt động trên máy Mac (OS X 10.11) nhưng không thuộc Centos 7.5. Tuy nhiên: điều này RewriteRulecũng viết lại vị trí của các tệp CSS chẳng hạn. Vì tôi chỉ cần chuyển hướng các tệp PHP, tôi đã sửa đổi quy tắc thành RewriteRule ^(.*)php$ index.php [L,QSA]. YMMV.
Laryx Decidua

1
Tôi rất vui vì nó đã giúp. Bạn đã đúng, nó nhắm mục tiêu TẤT CẢ các tệp vì câu hỏi là: " Chuyển hướng tất cả sang index.php bằng htaccess ". Có nhiều cách khác thanh lịch hơn để chỉ chuyển hướng các tệp PHP, chẳng hạn như RewriteRule ^(.*)\.php$ index.php [L,NE,QSA](không cần điều kiện để hoạt động). Tuy nhiên, ngày nay, tôi sử dụng một quy tắc rẻ tiền hơn : RewriteRule ^.+$ index.php [L,NE,QSA], có thể được kết hợp với các điều kiện RewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_FILENAME} !-d, hoặc thậm chí với RewriteCond $1 !^(index\.php|assets|robots\.txt|favicon\.ico)để thực sự cụ thể.
Julio Marchi

5

Trả lời ngớ ngẩn nhưng nếu bạn không thể hiểu tại sao nó không chuyển hướng kiểm tra xem phần sau có được bật cho thư mục web không ..

AllowOverride All

Điều này sẽ cho phép bạn chạy htaccess phải chạy! (có những lựa chọn thay thế nhưng không bật sẽ gây ra sự cố https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride )


0

Sau khi thực hiện, đừng quên thay đổi thẻ neo của bạn, về nhà

Thí dụ:

.htacces file
RewriteEngine On

RewriteRule ^about/$ /about.php

PHP file:
<a href="about/"> about</a>

Luôn nhớ thay đổi thẻ <a>.
Collins Benson

2
Sau khi thực hiện không thay đổi thẻ của bạn, nhà nghĩa là gì?
Enrico Maria De Angelis

0

chỉ trong trường hợp bạn vẫn đang tự hỏi làm thế nào để chuyển hướng tất cả yêu cầu nếu thư mục tồn tại (đối với các thư mục và tệp khung lõi) đến trình xử lý chỉ mục khung, sau một số lần thử lỗi / thành công tôi chỉ cần thay đổi RewriteCond trong .htaccess tập tin

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

các điều kiện trên nêu "không tìm thấy tệp" và "không tìm thấy thư mục", ok, nếu chỉ xóa dòng "không tìm thấy" (! -d) và kết thúc bằng một cái gì đó như dưới đây:

RewriteEngine on
RewriteBase /framework/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /framework/index.php [L,QSA]

Nó làm việc cho tôi như một lá bùa

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.