เปลี่ยนเส้นทางทั้งหมดไปที่ index.php โดยใช้ htaccess


131

ฉันกำลังเขียนเฟรมเวิร์ก MVC-ish ที่ใช้ PHP อย่างง่าย ฉันต้องการให้กรอบนี้สามารถติดตั้งในไดเร็กทอรีใดก็ได้

สคริปต์ PHP ของฉันคว้าคำขอ uri และแบ่งออกเป็นส่วนต่างๆ ทำให้ส่วนที่ 1 เป็นตัวควบคุมและส่วนที่ 2 ดำเนินการ สิ่งนี้ใช้ได้ดีเมื่อฉันทำสิ่งนี้:

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

มันจะไปที่ตัวควบคุมโมดูลเฉพาะและวิธีการ ตอนนี้ฉันมีตัวควบคุมเริ่มต้นคือตัวควบคุมบ้านซึ่งอยู่ในโฟลเดอร์โฮม

ตอนนี้เมื่อฉันเข้าถึงโฟลเดอร์นี้โดยตรง http://www.example.com/mvc/home/ มันจะแสดง 403 ต้องห้ามเนื่องจากมีโฟลเดอร์นี้อยู่ แต่ควรกลับไปที่ http://www.example.com ด้วย /mvc/index.php

ถ้าฉันจะติดตั้งเฟรมเวิร์กในโฟลเดอร์อื่นสมมติว่าโฟลเดอร์เฟรมเวิร์กต้องเปลี่ยนเส้นทางกลับไปที่http://www.example.com/framework/index.php

ฉันต้องการเปลี่ยนเส้นทางทุกโฟลเดอร์และไฟล์ php กลับไปที่ index.php โดยปล่อยให้ทุกอย่างเป็นไปตามนั้น

ปัญหาแรกของฉันที่ฉันพบคือมันไม่เคยเปลี่ยนเส้นทางไปยังโฟลเดอร์ที่ถูกต้องไปยังโฟลเดอร์รากของโดเมนเสมอ

นี่คือสิ่งที่ฉันลอง:

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

เพื่อให้แน่ใจว่าฉันเข้าใจคำถามของคุณอย่างถูกต้อง: คุณต้องการเปลี่ยนเส้นทางทุกคำขอไปยังรูท index.phpหรือคุณต้องการเปลี่ยนเส้นทางทุกคำขอที่ส่งไปยังโฟลเดอร์นั้น ๆ index.php ?
เท

ไปยังโฟลเดอร์ที่ไฟล์ htaccess อยู่ในไดเร็กทอรี root ของเฟรมเวิร์ก ในตัวอย่างของฉันกลับไปที่ไดเรกทอรี mvc
David Ericsson

คำตอบ:


259

กฎการเขียนซ้ำของคุณเกือบใช้ได้

ขั้นแรกตรวจสอบให้แน่ใจว่า.htaccessไฟล์ของคุณอยู่ในรูทเอกสารของคุณ (ที่เดียวกับindex.php) มิฉะนั้นจะมีผลกับโฟลเดอร์ย่อยที่อยู่ในนั้นเท่านั้น (และโฟลเดอร์ย่อยใด ๆ ภายในนั้น - เรียกซ้ำ)

จากนั้นทำการเปลี่ยนแปลงเล็กน้อยกับกฎของคุณเพื่อให้ดูเหมือนว่า:

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

ในขณะที่คุณกำลังจับคู่.ซึ่งเป็นหนึ่งในตัวอักษรใด ๆ คุณต้องมีอย่างน้อย.*เพื่อจับคู่อินสแตนซ์ของอักขระใด ๆ

$_GET['path']ตัวแปรจะมีโครงสร้างไดเรกทอรีปลอมเพื่อให้/mvc/module/testเช่นที่คุณสามารถใช้ใน index.php เพื่อตรวจสอบการควบคุมและการกระทำที่คุณต้องการดำเนินการ


หากคุณต้องการให้ shebang ทั้งหมดติดตั้งในไดเร็กทอรีย่อยเช่น/mvc/หรือ/framework/วิธีที่ซับซ้อนน้อยที่สุดในการทำคือเปลี่ยนกฎการเขียนซ้ำเล็กน้อยเพื่อนำมาพิจารณา

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

และตรวจสอบให้แน่ใจว่าคุณindex.phpอยู่ในโฟลเดอร์นั้นในขณะที่.htaccessไฟล์อยู่ในรูทของเอกสาร


ทางเลือกในการ$_GET['path'] (อัปเดตเมื่อ ก.พ. 61 และ ม.ค. 62)

ไม่จำเป็นจริงๆ (หรือแม้แต่ตอนนี้) ในการกำหนดเส้นทางเป็น$_GETตัวแปรเฟรมเวิร์กจำนวนมากจะอาศัย$_SERVER['REQUEST_URI']การดึงข้อมูลเดียวกัน - โดยปกติเพื่อกำหนดว่าจะใช้คอนโทรลเลอร์ตัวใด - แต่หลักการก็เหมือนกันทุกประการ

สิ่งนี้จะทำให้ง่ายขึ้นRewriteRuleเล็กน้อยเนื่องจากคุณไม่จำเป็นต้องสร้างพารามิเตอร์path (ซึ่งหมายความว่าต้นฉบับของ OP RewriteRule จะใช้งานได้แล้ว):

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

อย่างไรก็ตามกฎเกี่ยวกับการติดตั้งในไดเร็กทอรีย่อยยังคงมีผลเช่น

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



ธง:

NC = ไม่มีกรณี (ไม่คำนึงถึงขนาดตัวพิมพ์ไม่จำเป็นจริงๆเนื่องจากไม่มีอักขระในรูปแบบ)

L = สุดท้าย (จะหยุดเขียนใหม่หลังจากการเขียนซ้ำนี้ดังนั้นโปรดตรวจสอบให้แน่ใจว่านี่เป็นสิ่งสุดท้ายในรายการการเขียนซ้ำของคุณ)

QSA= Query String Append ในกรณีที่คุณมีบางอย่าง?like=penguinsในตอนท้ายที่คุณต้องการเก็บไว้และส่งต่อไปที่ index.php


1
ควรเป็น index.php? path = $ 1
Jacek Pietal

1
@Prozi ไม่ใช่ถ้าคุณอยู่ในไดเรกทอรีย่อยและindex.phpอยู่ใน docroot คุณต้องมี / - with Options +Indexesและindex.phpชั้นนำที่รวมอยู่ในนั้นDirectoryIndexคุณสามารถออกจากindex.phpทั้งหมดและใช้/?path=$1สิ่งนี้ถือเป็นจริงเมื่อ ทำการเขียนซ้ำผ่าน. htaccess แทนที่จะเป็น<Directory>คำสั่งประเภทhttpd-vhosts.conf
CD001

หากคุณใช้สิ่งนั้นและพึ่งพา $ _GET ['path'] คุณจะประสบปัญหาในกรณีที่ย้ายไปยังเซิร์ฟเวอร์ nginx ...
barell

3
โพสต์ได้ดี! เป็นที่น่าสังเกตว่าผู้ใช้สามารถเขียนทับได้$_GET['path']หากเพิ่มลงpath=whateverใน URL
rybo111

1
@Liviuge - จริง แต่ตอนแรกฉันเดินผ่านเส้นทางทั้งหมดไปถึง$_GETมันจะต้อง(.*)... มันตลก แต่ RewriteRule ที่ OP ใช้เมื่อ 6 ปีที่แล้วไม่ได้ผลสำหรับพวกเขา - แต่ด้วยวิธีที่สถาปัตยกรรม MVC มี พัฒนาด้วย PHP (ตามที่ฉันใส่ไว้ในอัปเดตเมื่อวันที่ 18 กุมภาพันธ์ ) ตอนนี้ ... เดาว่าพวกเขามาก่อนเวลา :) ยังคงต้องการเส้นทางที่ถูกต้องไปยัง/mvc/ไดเรกทอรีแน่นอน
CD001

29

หากต้องการเปลี่ยนเส้นทางทุกสิ่งที่ไม่มีindex.phpคุณสามารถใช้FallBackResourceคำสั่ง

FallbackResource /index.php

มันทำงานได้เช่นเดียวกับErrorDocumentเมื่อคุณขอเส้นทางที่ไม่มีอยู่จริงหรือแฟ้มบนเซิร์ฟเวอร์สั่งเงียบ forwords index.phpการร้องขอไปยัง

หากคุณต้องการเปลี่ยนเส้นทางทุกอย่าง ( including existant files or folders) ไปที่index.phpคุณสามารถใช้สิ่งต่อไปนี้:

RewriteEngine on

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

สังเกตว่ารูปแบบ^((?!index\.php).+)$ ตรงกับ uri ใด ๆ ยกเว้นindex.phpเราได้ยกเว้นเส้นทางปลายทางเพื่อป้องกันข้อผิดพลาดในการวนซ้ำแบบไม่สิ้นสุด


แต่คุณอาจต้องการใช้:DirectoryIndex index.php
Shao

1
ใช้*แทน+ในรูปแบบหากคุณต้องการเปลี่ยนเส้นทางรูทเองด้วย
Mir-Ismaili

การใช้ xampp ใน win 10 64 บิตนี่คือกฎการเขียนซ้ำที่ใช้ได้กับอินสแตนซ์ของฉัน
nwolybug

15

คุณสามารถใช้สิ่งนี้:

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

สิ่งนี้จะเปลี่ยนเส้นทางแบบสอบถามทั้งหมดไปยัง index.php ของไดเรกทอรีราก โปรดทราบว่าจะเปลี่ยนเส้นทางการสืบค้นสำหรับไฟล์ที่มีอยู่เช่นรูปภาพไฟล์จาวาสคริปต์หรือสไตล์ชีต


1
วิธีนี้เกือบจะได้ผลสำหรับฉัน ฉันได้รับ "AH00124: คำขอเกินขีด จำกัด ของการเปลี่ยนเส้นทางภายใน 10 ครั้ง" ฉันได้เพิ่ม "RewriteRule ^ index \ .php - [L]" ไว้ก่อนแล้วและมันก็ทำงานได้อย่างสมบูรณ์แบบ!
Fredster

11

มี "เคล็ดลับ" อย่างหนึ่งสำหรับปัญหานี้ที่เหมาะกับทุกสถานการณ์วิธีแก้ปัญหาที่ชัดเจนซึ่งคุณจะต้องลองใช้เพื่อให้เชื่อว่าใช้งานได้จริง ... :)

นี่มัน ...

<IfModule mod_rewrite.c>

   RewriteEngine On

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

</IfModule>

โดยทั่วไปคุณจะขอให้MOD_REWRITEส่งต่อไปยังindex.phpคำขอ URI ทุกครั้งเมื่อมีไฟล์อยู่และทุกครั้งเมื่อไม่มีไฟล์ที่ร้องขอ !

เมื่อตรวจสอบซอร์สโค้ดของMOD-REWRITEเพื่อทำความเข้าใจว่ามันทำงานอย่างไรฉันพบว่าการตรวจสอบทั้งหมดเกิดขึ้นหลังจากการตรวจสอบเสมอว่ามีไฟล์ที่อ้างอิงอยู่หรือไม่ จากนั้นRegExจะประมวลผลเท่านั้น แม้ว่า URI ของคุณจะชี้ไปที่โฟลเดอร์ Apache ก็จะบังคับใช้การตรวจสอบไฟล์ดัชนีที่อยู่ในไฟล์คอนฟิกูเรชัน

จากการค้นพบที่เรียบง่ายนั้นเห็นได้ชัดว่าการตรวจสอบไฟล์อย่างง่ายจะเพียงพอสำหรับการโทรที่เป็นไปได้ทั้งหมดเท่าที่เราแตะสองครั้งที่การตรวจสอบการมีไฟล์และกำหนดเส้นทางผลลัพธ์ทั้งสองไปยังจุดสิ้นสุดเดียวกันซึ่งครอบคลุมความเป็นไปได้ 100%

สำคัญ:หนังสือเชิญไม่มี " / " index.phpใน โดยค่าเริ่มต้นMOD_REWRITEจะใช้โฟลเดอร์ที่ตั้งไว้เป็น "โฟลเดอร์ฐาน" สำหรับการส่งต่อ ความสวยงามของมันคือไม่จำเป็นต้องเป็น "โฟลเดอร์ราก" ของไซต์การอนุญาตให้โซลูชันนี้ใช้ได้กับlocalhost/และ / หรือโฟลเดอร์ย่อยใด ๆ ที่คุณใช้

ในที่สุดโซลูชันอื่น ๆ ที่ฉันได้ทดสอบไปก่อนหน้านี้ (วิธีที่ดูเหมือนจะใช้งานได้ดี) ทำให้ความสามารถของ PHP "ต้องการ" ไฟล์ผ่านเส้นทางสัมพัทธ์ซึ่งเป็นคนเกียจคร้าน ระวัง.

บางคนอาจบอกว่านี่เป็นวิธีแก้ปัญหาที่ไม่สง่างาม อาจเป็นจริง แต่จากการทดสอบในหลาย ๆ สถานการณ์เซิร์ฟเวอร์หลายเครื่อง Apache เวอร์ชันต่างๆ ฯลฯ วิธีนี้ใช้ได้ผล 100% ในทุกกรณี!


ขอบคุณสิ่งนี้แก้ไขปัญหาของฉันโดยที่FallbackResource index.phpสายทำงานบน Mac (OS X 10.11) แต่ไม่ได้อยู่ภายใต้ Centos 7.5 อย่างไรก็ตามสิ่งนี้RewriteRuleยังเขียนตำแหน่งของไฟล์ CSS เช่นกัน เนื่องจากฉันต้องการเปลี่ยนเส้นทางเฉพาะไฟล์ PHP ฉันจึงแก้ไขกฎเป็นRewriteRule ^(.*)php$ index.php [L,QSA]. YMMV
Laryx Decidua

1
ฉันมีความสุขที่ได้ช่วย คุณพูดถูกมันกำหนดเป้าหมายไฟล์ทั้งหมดเพราะคำถามคือ: " เปลี่ยนเส้นทางทั้งหมดไปที่ index.php โดยใช้ htaccess " มีวิธีอื่น ๆ ที่สวยงามกว่าในการเปลี่ยนเส้นทางไฟล์ PHP เท่านั้นเช่นRewriteRule ^(.*)\.php$ index.php [L,NE,QSA](ซึ่งไม่จำเป็นต้องมีเงื่อนไขในการทำงาน) อย่างไรก็ตามทุกวันนี้ฉันใช้กฎที่ไม่แพงมากขึ้น: RewriteRule ^.+$ index.php [L,NE,QSA]ซึ่งสามารถใช้ร่วมกับเงื่อนไขRewriteCond %{REQUEST_FILENAME} !-fและRewriteCond %{REQUEST_FILENAME} !-dหรือแม้กระทั่งRewriteCond $1 !^(index\.php|assets|robots\.txt|favicon\.ico)เพื่อให้เฉพาะเจาะจงอย่างแท้จริง
Julio Marchi

5

คำตอบโง่ ๆ แต่ถ้าคุณคิดไม่ออกว่าทำไมไม่เปลี่ยนเส้นทางตรวจสอบว่าเปิดใช้งานสิ่งต่อไปนี้สำหรับโฟลเดอร์เว็บแล้ว ..

AllowOverride All

สิ่งนี้จะช่วยให้คุณสามารถเรียกใช้ htaccess ซึ่งต้องทำงานอยู่! (มีทางเลือกอื่น แต่ไม่เปิดจะทำให้เกิดปัญหาhttps://httpd.apache.org/docs/2.4/mod/core.html#allowoverride )


0

หลังจากทำเสร็จแล้วอย่าลืมเปลี่ยนแท็กจุดยึดที่บ้าน

ตัวอย่าง:

.htacces file
RewriteEngine On

RewriteRule ^about/$ /about.php

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

อย่าลืมเปลี่ยนแท็ก <a>
Collins Benson

2
อะไรหลังจากทำไม่ได้ที่จะเปลี่ยนแท็กของคุณที่บ้านหมายถึงอะไร?
Enrico Maria De Angelis

0

ในกรณีที่คุณยังสงสัยว่าจะเปลี่ยนเส้นทางคำขอทั้งหมดได้อย่างไรหากมีไดเร็กทอรีอยู่ (สำหรับโฟลเดอร์เฟรมเวิร์กหลักและไฟล์) ไปยังตัวจัดการดัชนีเฟรมเวิร์กหลังจากเกิดข้อผิดพลาด / ความสำเร็จบางอย่างเพิ่งสังเกตเห็นว่าฉันต้องการเปลี่ยน RewriteCond ใน. htaccess ไฟล์

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

เงื่อนไขข้างต้นระบุว่า "not found files" และ "not found directory" โอเคจะเกิดอะไรขึ้นถ้าเพียงแค่ลบบรรทัด "not found" (! -d) และลงท้ายด้วยสิ่งต่อไปนี้:

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

มันได้ผลสำหรับฉันเหมือนมีเสน่ห์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.