Thay đổi url bằng htaccess

Oct 20 2020

Tôi có một bản trình bày web với một số địa chỉ url điển hình. Bây giờ tôi cần thêm một quy tắc viết lại cho một ngôn ngữ khác, ví dụ:

domain/club -> do not change
domain/club/path -> do not change
domain/club/path?search=somethingelse -> do not change
domain/en/club -> domain/club?lang=en
domain/en/club/path -> domain/club/path?lang=en
domain/en/club/path?search=something -> domain/club/path?search=something&lang=endomain

Ý tưởng của tôi là chia nó thành các nhóm miền / ngôn ngữ / câu lạc bộ / đường dẫn? Search = something và sau đó viết

RewriteRule \/(?<language>[a-zA-Z]{2})\/club\/?(?<path>.*)\?(?<search>.*)   /club/$1?search=$2&lang=$3

nhưng điều này sẽ không xem xét các chuỗi không có ?. Tôi cũng không biết làm thế nào để giải quyết sự khác biệt với hai trường hợp ?lang=và &lang=. Tôi không tìm thấy bất cứ điều gì trực tuyến.

Tôi đang làm điều này trên khuôn khổ PHP hiện có (không phải bất kỳ tiêu chuẩn nào) và do đó tôi phải làm theo cách này (hiểu với các url cụ thể đó).

Trả lời

3 MrWhite Oct 20 2020 at 00:36

Có vẻ như bạn đang làm cho việc này phức tạp hơn thực tế. Trừ khi bạn cần cụ thể về việc đối sánh "câu lạc bộ", có vẻ như bạn chỉ cần xóa phân đoạn đường dẫn đầu tiên khi phân đoạn đó giống như mã ngôn ngữ 2 chữ cái và thay vào đó di chuyển đoạn này sang langtham số URL trong chuỗi truy vấn.

Đối với điều này, bạn có thể làm như sau, ở gần đầu .htaccesstệp của bạn :

RewriteRule ^([a-z]{2})/(.+) $2?lang=$1 [QSA,L]

Yêu cầu cho /en/clubsẽ được ghi lại thành /club?lang=envà /en/club/path?search=somethingđến /club/path?lang=en&search=something(lưu ý rằng langtham số URL là đầu tiên).

Giải trình:

  • Các RewriteRule mô hình phù hợp chống lại các URL-con đường duy nhất, không phải là chuỗi truy vấn. Đường dẫn URL phù hợp cũng không có tiền tố gạch chéo.
  • ([a-z]{2})- khớp với mã ngôn ngữ gồm 2 ký tự (viết thường). (Mặc dù trong regex của bạn, bạn cũng cho phép viết hoa?) Đây là một subpattern bắt giữ, do đó, được lưu trữ tự nhiên trong $1backreference (đầu tiên) .
  • Các (.+)kết quả khớp với mọi thứ trong đường dẫn URL theo sau phân đoạn đường dẫn mã ngôn ngữ (và dấu gạch chéo). Lưu ý rằng điều này phù hợp với một cái gì đó , không phải không có gì . Vì vậy, nó sẽ không thành công cho một yêu cầu /en/, chỉ /en/<something>. (Nếu nhu cầu này để thành công cho /en/ chỉ cũng sau đó thay đổi subpattern này để (.*).) Đây là cũng chụp và lưu trữ trong (thứ hai) $2backreference. ví dụ. Yêu cầu /en/club/pathvà lưu $2giữ club/path.
  • Các QSAlá cờ gắn thêm bất kỳ chuỗi truy vấn có thể có mặt trên yêu cầu ban đầu và xử lý các "sáp nhập" với bất kỳ chuỗi truy vấn trong thay chuỗi. ví dụ. search=something. Tuy nhiên, một sự khác biệt nhỏ với ví dụ của bạn là langtham số URL sẽ là đầu tiên , không phải cuối cùng - mặc dù đó không phải là vấn đề.

Tuy nhiên, điều này có hiệu quả hay không vẫn phụ thuộc vào cách "PHP framework" của bạn định tuyến các URL. Ví dụ: nếu nó giống như WordPress và nhìn vào $_SERVER['REQUEST_URI']superglobal PHP thì nó sẽ vẫn thấy đường dẫn URL trước khi viết lại.

Bạn có lẽ có những bài viết lại khác theo sau này?


RewriteRule \/(?<language>[a-zA-Z]{2})\/club\/?(?<path>.*)\?(?<search>.*) /club/$1?search=$2&lang=$3

nhưng điều này sẽ không xem xét các chuỗi không có ?. Tôi cũng không biết làm thế nào để giải quyết sự khác biệt với hai trường hợp ?lang=và &lang=. Tôi không tìm thấy bất cứ điều gì trực tuyến.

Có một số vấn đề ở đây:

  • Regex không được gắn vào đầu đường dẫn URL, vì vậy nó khớp /<anything>/en/etc.
  • Như đã lưu ý ở trên, đường dẫn URL phù hợp với RewriteRule mẫu không bắt đầu bằng dấu gạch chéo.
  • "điều này sẽ không coi là các chuỗi không có ?" - URL được khớp với RewriteRule mẫu chỉ là đường dẫn URL. Điều này không bao gồm chuỗi truy vấn. Vì vậy, cố gắng khớp chuỗi truy vấn ở đây sẽ không thành công. (Nếu bạn cần khớp với chuỗi truy vấn thì bạn cần một RewriteCondchỉ thị bổ sung và khớp với QUERY_STRINGbiến máy chủ.)
  • Không phải là lỗi, nhưng không cần phải gạch chéo ngược-thoát các dấu gạch chéo trong regex vì dấu gạch chéo không có ý nghĩa đặc biệt ở đây ( dấu cách là dấu phân cách regex / đối số trong tệp cấu hình Apache). Như đã lưu ý, đây không hoàn toàn là một lỗi, vì bạn có thể thoát dấu gạch chéo ngược hầu hết các ký tự, nhưng nó làm phức tạp regex và khiến nó khó đọc hơn.
  • Bạn đang sử dụng các nhóm đã được đặt tên (được hỗ trợ trong Apache 2.4.8+) nhưng bạn đang sử dụng các tham chiếu số phụ trong chuỗi thay thế . Bạn không thể sử dụng cả hai. (Sẽ dễ dàng hơn khi ở lại với IMO backreferences số.)
  • Các tham chiếu ngược trong chuỗi thay thế dường như không đúng thứ tự. $1là mã ngôn ngữ. ví dụ. nó sẽ giống hơn (mặc dù điều này vẫn chưa chính xác)./club/$2?search=$3&lang=$1
  • "cách giải quyết sự khác biệt với hai trường hợp ?lang=và &lang=" - QSACờ (Nối chuỗi truy vấn) thực hiện việc này cho bạn. Ngoại trừ việc chuỗi truy vấn được nối thêm , không được thêm tiền tố .