Referans: mod yeniden yazma, URL yeniden yazma ve" güzel bağlantılar " açıkladı

"Pretty links" genellikle istenen bir konudur, ancak nadiren tam olarak açıklanmıştır. mod_rewrite "güzel bağlantılar" yapmanın bir yoludur, ancak karmaşıktır ve sözdizimi çok terse, grok zordur ve Dokümantasyon HTTP belirli bir düzeyde yeterlilik varsayar. Birisi basit terimlerle "güzel bağlantılar" nın nasıl çalıştığını ve mod_rewrite'in bunları oluşturmak için nasıl kullanılabileceğini açıklayabilir mi?

diğer ortak isimler, takma adlar, temiz URL'ler için şartlar: RESTful URL'ler, kullanıcı dostu URL'ler, SEO dostu URL'ler, Slugging, MVC URL'ler (muhtemelen bir yanlış isim)

128
tarihinde sordu Taryn 2013-12-13 14:07:37
kaynak

4 ответов

ne mod_rewrite anlamak için ilk bir web sunucusu nasıl çalıştığını anlamak gerekir. Bir web sunucusu HTTP istekleri yanıt verir . En temel seviyesinde bir HTTP isteği şöyle görünüyor:

GET /foo/bar.html HTTP/1.1

bu ondan URL /foo/bar.html isteyen bir web sunucusuna bir tarayıcı basit bir istek. dosyası talep etmediğini vurgulamak önemlidir , sadece bazı keyfi URL ister. İstek de şu şekilde görünebilir:

GET /foo/bar?baz=42 HTTP/1.1

bu, bir URL için geçerli bir istektir ve dosyalarla ilgisi yoktur.

web sunucusu, bir bağlantı noktasında dinleyen, o bağlantı noktasında gelen HTTP isteklerini kabul eden ve bir yanıt döndüren bir uygulamadır. Bir web sunucusu, yapılandırdığınız herhangi bir şekilde/uygun gördüğü herhangi bir şekilde herhangi bir isteğe yanıt vermek için tamamen ücretsizdir cevap vermek. Bu yanıt bir dosya değil, herhangi bir diskteki fiziksel dosyalarla ilgisi olabilecek veya olmayan bir HTTP yanıtı . Bir Web sunucusunun Apache olması gerekmez, ısrarla çalışan ve HTTP isteklerine yanıt veren bir bağlantı noktasına bağlı olan tüm programlar olan diğer birçok web sunucusu vardır. Kendin yazabilirsin. Bu paragraf, URL'lerin doğrudan dosya eşit olduğu herhangi bir düşünceden sizi boşanmak için tasarlandı, ki bu gerçekten önemlidir anlamak. :)

çoğu web sunucusunun varsayılan yapılandırması, sabit diskteki URL ile eşleşen bir dosya aramaktır. Sunucunun belge kökü , /var/www olarak ayarlanırsa, /var/www/foo/bar.html dosyasının var olup olmadığına bakabilir ve eğer öyleyse hizmet edebilir. Dosya biterse".php "PHP tercümanını çağırır ve sonra sonucu döndürür. Tüm bu dernek tamamen yapılandırılabilir; bir dosya değil bitmek zorunda".php" Web sunucusu PHP tercüman aracılığıyla çalıştırmak için, ve URL gerçekleşmesi için diskte herhangi bir belirli dosya eşleşmesi gerekmez.

mod_rewrite rewrite iç istek işleme için bir yoldur. Web sunucusu /foo/bar URL'si için bir istek aldığında, rewrite web sunucusu eşleşecek diskte bir dosya arayacaktır önce başka bir şey içine URL. Basit örnek:

RewriteEngine On
RewriteRule   /foo/bar /foo/baz

bu kural diyor bir istek eşleştiğinde "/foo/bar", "/foo/baz"olarak yeniden yazın. isteği daha sonra /foo/baz yerine istendiği gibi ele alınacaktır. Bu, çeşitli efektler için kullanılabilir, örneğin:

RewriteRule (.*) .html

bu kural bir şeyle eşleşir ( .* ) ve , ( (..) ), daha sonra eklemek için yeniden yazar".html". Başka bir deyişle, Eğer /foo/bar istenen URL idi, /foo/bar.html istendiği gibi ele alınacaktır. Bkz. http://regular-expressions.info düzenli ifade eşleştirme, yakalama ve değiştirmeler hakkında daha fazla bilgi için.

başka sık karşılaşılan kural şudur:

RewriteRule (.*) index.php?url=

bu, yine, herhangi bir şeyle eşleşir ve dosya dizinine yeniden yazar. url sorgusunda eklenen başlangıçta istenen URL ile php parametre. Yani... gelen tüm ve tüm istekler için dosya dizini.php yürütülür ve bu dosya $_GET['url'] orijinal isteğine erişimi olacak, bu yüzden onunla istediği her şeyi yapabilirsiniz.

öncelikle web sunucusu yapılandırma dosyası içine bu yeniden yazma kuralları koymak . Apache ayrıca* belge kökünüz içinde .htaccess adlı bir dosyaya koymanıza izin verir (örn .php dosyaları).

* eğer birincil Apache yapılandırma dosyası tarafından izin; bu isteğe bağlı, ancak genellikle etkin.

mod_rewrite ne yapar değil do

mod_rewrite sihirli tüm URL'leri "güzel"yapmaz. Bu ortak bir yanlış anlama. Web sitenize bu bağlantıyı varsa:

<a href="/my/ugly/link.php?is=not&amp;very=pretty">

mod_rewrite bunu güzel yapmak için yapabileceği bir şey yok. İçin bunu güzel bir bağlantı yapmak için şunları yapmanız gerekir:

  1. bağlantıyı güzel bir bağlantıya değiştirin:

    <a href="/my/pretty/link">
    
  2. , yukarıda açıklanan yöntemlerden herhangi birini kullanarak /my/pretty/link URL'sine olan talebi işlemek için sunucuda mod_rewrite kullanın.

(bir mod_substitute dönüşüm için birlikte kullanabilirsiniz HTML sayfaları ve içerdiği bağlantılar. Bu, HTML kaynaklarınızı güncellemekten daha fazla çaba göstermekle birlikte.)

mod_rewrite yapabileceğiniz çok şey var ve oluşturabileceğiniz çok karmaşık eşleştirme kuralları, çeşitli yeniden yazıların zincirlenmesi, tamamen farklı bir hizmete veya makineye proxying istekleri, yanıt olarak belirli HTTP durum kodlarını döndürülmesi, istekleri yönlendirme vb. Bu çok güçlü ve temel anlamak eğer çok iyi kullanılabilir HTTP istek-yanıt mekanizması. değil otomatik olarak bağlantıları güzel yapmak yok.

olası tüm bayraklar ve seçenekler için resmi Dokümantasyon bakın.

90
cevap deceze 2018-05-15 19:03:30
kaynak

deceze'nin cevabı üzerinde genişletmek için birkaç örnek ve diğer bazı mod_rewrite işlevselliğinin açıklaması sağlamak istedim.

aşağıdaki örneklerin tümü, .htaccess dosyanıza RewriteEngine On eklediğinizi varsayar.

Yeniden Yazma Örneği

bu örneği alalım:

RewriteRule ^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$ /blog/index.php?id=&title= [NC,L,QSA]

kural 4 bölüme ayrılmıştır:

  1. RewriteRule -
  2. yeniden yazma kuralını başlatır
  3. ^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$ - bu desen denir, ancak kuralın sol tarafı olarak ona atıfta bulunacağım -
  4. den yeniden yazmak istediğiniz şey
  5. blog/index.php?id=&title= - bir yeniden yazma kuralının ikamesi veya sağ tarafı olarak adlandırılır -
  6. ye yeniden yazmak istediğiniz şey
  7. [NC,L,QSA] , daha fazlasını açıklayacağım bir virgülle ayrılmış yeniden yazma kuralı için bayraklardır daha sonra

yukarıdaki yeniden yazma, /blog/1/foo/ gibi bir şeye bağlanmanıza izin verecek ve aslında /blog/index.php?id=1&title=foo yükleyecektir .

kuralın sol tarafı

  • ^ sayfa adının başlangıcını gösterir - bu yüzden example.com/blog/... yeniden yazacak ama example.com/foo/blog/...
  • parantez (…) her set biz yakalayabilir düzenli bir ifade temsil eder kuralın sağ tarafında bir değişken olarak. Bu örnekte:
    • ilk parantez seti - ([0-9]+) - en az 1 karakter uzunluğunda ve yalnızca sayısal değerlerle (yani 0-9) bir dizeyle eşleşir. Bu kuralın
    • sağ tarafında ile başvurulabilir
    • ikinci parantez kümesi, yalnızca alfanümerik karakterler (A-Z, A-z veya 0-9) içeren en az 1 karakter uzunluğunda bir dizeyle eşleşir veya - veya + (not + bu regex tekrarlama karakteri olarak yürütecek kaçmadan bir ters eğik çizgi ile kaçtı ). Bu kuralın
    • sağ tarafında ile başvurulabilir
  • ? , önceki karakterin isteğe bağlı olduğu anlamına gelir, bu nedenle bu durumda hem /blog/1/foo/ hem de /blog/1/foo aynı yere yeniden yazılır
  • $ , bunun
  • ile eşleşmek istediğimiz dizenin sonu olduğunu gösterir

bayraklar

bunlar, belirli koşulları belirtmek için yeniden yazma kuralınızın sonunda köşeli parantezlere eklenen seçeneklerdir. Yine, belgelerinde okuyabileceğiniz çok sayıda farklı bayrak var, ancak daha yaygın bayraklardan bazılarını geçeceğim:

NC

no case bayrağı anlamına gelir yeniden yazma kuralı büyük / küçük harf duyarsızdır, bu nedenle yukarıdaki örnek kural için /blog/1/foo/ ve /BLOG/1/foo/ (veya bunun herhangi bir varyasyonu) eşleşmesi anlamına gelir.

L

son bayrak, işlenmesi gereken son kural olduğunu gösterir. Bu, Eğer ve yalnızca bu kural eşleşirse, geçerli yeniden yazma işleme çalıştırmasında başka hiçbir kural değerlendirilmeyeceği anlamına gelir. Kural eşleşmezse, diğer tüm kurallar aşağıdaki gibi denenecektir her zamanki. L bayrağını ayarlamıyorsanız, aşağıdaki tüm kurallar yeniden yazılmış URL'sine uygulanır.

END

Apache 2.4'ten bu yana [END] bayrağını da kullanabilirsiniz. Onunla eşleşen bir kural tamamen daha fazla takma ad/yeniden yazma işlemini sonlandırır. ( [L] bayrağı, örneğin alt dizinlere veya alt dizinlere yeniden yazarken ikinci bir tur tetikleyebilir.)

QSA

sorgu dizesi ekleme bayrağı, orijinal get parametrelerine eklenecek belirtilen URL'ye ekstra değişkenlerde geçmemizi sağlar. Örneğimiz için bu, /blog/1/foo/?comments=15 gibi bir şeyin /blog/index.php?id=1&title=foo&comments=15

yükleyeceği anlamına gelir
R

bu bayrak yukarıdaki örnekte kullandığım bir bayrak değil, ama bahsetmeye değer düşündüğüm bir bayrak. Bu durum kodu (örn. R=301 ). Örneğin, /myblog/ to /blog / üzerinde 301 yönlendirme yapmak isterseniz, böyle bir kural yazmanız yeterlidir:

RewriteRule ^/myblog/(*.)$ /blog/ [R=301,QSA,L]

Rewrite Koşulları

rewrite koşulları rewrites daha da güçlü hale getirir ve daha spesifik durumlar için yeniden yazmaları belirtmenize izin verir. belgelerinde okuyabileceğiniz birçok koşul var, ancak bir birkaç ortak örnek ve bunları açıklamak:

# if the host doesn't start with www. then add it and redirect
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

bu, alanınızı www. (zaten yoksa) ile ön plana çıkaracak ve 301 yönlendirme yürütecek çok yaygın bir uygulamadır. Örneğin, http://example.com/blog/ yükleme http://www.example.com/blog/

yönlendirecektir
# if it cant find the image, try find the image on another domain
RewriteCond %{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)$ http://www.example.com/ [L]

bu biraz daha az yaygındır, ancak dosya adı sunucuda bulunan bir dizin veya dosya olup olmadığını yürütmeyen bir kuralın iyi bir örneğidir.

  • %{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC] sadece JPG, jpeg, gıf veya png (büyük / küçük harf duyarsız) bir dosya uzantısı ile dosyalar için yeniden yürütecek.
  • %{REQUEST_FILENAME} !-f , dosyanın geçerli sunucuda olup olmadığını kontrol eder ve yalnızca
  • değilse yeniden yazmayı çalıştırır
  • %{REQUEST_FILENAME} !-d , dosyanın geçerli sunucuda olup olmadığını kontrol eder ve yalnızca
  • değilse yeniden yazmayı çalıştırır
  • yeniden yazma aynı dosyayı başka bir etki alanına yüklemeye çalışacaktır
69
cevap Nick 2017-05-23 13:31:09
kaynak

Referanslar

yığın taşması var birçok başlamak için diğer büyük kaynaklar:

ve yeni gelen dostu regex genel bakış:

-kullanılmış yer tutucular

  • .* boş bir dize bile herhangi bir şeyle eşleşir. Bu deseni her yerde kullanmak istemezsiniz, ancak genellikle son geri dönüş kuralında.
  • [^/]+ daha sık yol segmentleri için kullanılır. İleri eğik çizgiden başka bir şeyle eşleşiyor.
  • \d+ sadece sayısal dizelerle eşleşir.
  • \w+ alfasayısal karakterlerle eşleşir. Temel olarak [A-Za-z0-9_] için kısaltmadır .
  • [\w\-]+ için"sümüklü böcek" tarzı yol segmentleri, harf, sayı, çizgi - ve _
  • [\w\-.,]+ dönemleri ve virgül ekler. […] charclasses bir \- çizgi tercih.
  • \. bir edebi dönem gösterir. Aksi takdirde . dışında […] herhangi bir sembol için yer tutucudur.

bu yer tutucuların her biri genellikle (…) parantez içinde yakalama grubu olarak sarılır. Ve tüm desen genellikle ^………$ başlangıç + uç işaretçileri. "Desenler" alıntı isteğe bağlıdır.

RewriteRules

aşağıdaki örnekler PHP merkezli ve biraz daha artımlı, benzer durumlar için uyum daha kolaydır. Onlar sadece özetler, genellikle bağlantı daha fazla varyasyon veya detaylı Q & As.

  • statik haritalama

    /contact , /about

    iç dosya şemalarına birkaç sayfa adını kısaltmak en basit:

     RewriteRule ^contact$  templ/contact.html
     RewriteRule ^about$    about.php
    
  • sayısal tanımlayıcılar

    /object/123

    mevcut PHP komut dosyaları http://example.com/article/531 gibi kısayollar Tanıtımı da kolaydır. Sayısal yer tutucu sadece $_GET parametresi için yeniden eşleştirilebilir:

     RewriteRule ^article/(\d+)$    article-show.php?id=
     #                      └───────────────────────────┘
    
  • sülük tarzı tutucular

    /article/with-some-title-slug

    /article/title-string yer tutucuları için izin vermek için bu kuralı kolayca genişletebilirsiniz:

     RewriteRule ^article/([\w-]+)$    article-show.php?title=
     #                       └────────────────────────────────┘
    

    not senaryonuz bu başlıkları veritabanı kimliklerine geri eşleyebilmek (veya uyarlanmak) gerekir. RewriteRules yalnız oluşturmak veya ince hava dışarı bilgi tahmin edemez.

  • sayısal önekleri olan salyangozlar

    /readable/123-plus-title

    bu nedenle sık sık karışık /article/529-title-slug görürsünüz uygulamada kullanılan yollar:

     RewriteRule ^article/(\d+)-([\w-]+)$    article.php?id=&title=
     #                      └───────────────────────────────┘
    

    şimdi title= yi geçmeyi atlayabilirsiniz, çünkü komut dosyanız genellikle yine de veritabanı kimliğine güvenecektir. -title-slug keyfi URL dekorasyon haline gelmiştir.

  • - alternatif listelerle

    /foo/… /bar/… /baz/…

    birden çok sanal sayfa yolu için benzer kurallarınız varsa, | alternatif listeleriyle eşleştirebilir ve sıkıştırabilirsiniz. Ve yine sadece iç GET parametrelerine yeniden atayın:

     #                               ┌─────────────────────────┐
     RewriteRule ^(blog|post|user)/(\w+)$  disp.php?type=&id=
     #               └───────────────────────────────────┘
    

    bunları tek tek bölebilirsiniz RewriteRule bu çok karmaşık olmalı.

  • farklı backends
    ile ilgili URL'leri gönderme
    /date/SWITCH/backend

    alternatif listelerin daha pratik kullanımı, istek yollarını farklı komut dosyalarına eşlemektir. Örneğin, tarihlere dayalı daha eski ve daha yeni bir web uygulaması için tekdüze URL'ler sağlamak için:

     #                   ┌─────────────────────────────┐
     #                   │                 ┌───────────┼───────────────┐
     RewriteRule ^blog/(2009|2010|2011)/([\d-]+)/?$ old/blog.php?date=
     RewriteRule ^blog/(\d+)/([\d-]+)/?$  modern/blog/index.php?start=
     #                          └──────────────────────────────────────┘
    

    bu sadece bir komut dosyası üzerine 2009-2011 mesajları remaps, ve diğer tüm yıl başka bir işleyici için geçerlidir. daha spesifik kural ilk geliyor unutmayın . Her komut dosyası farklı get params kullanabilir.

  • diğer sınırlayıcılar sadece / yol slashes

    /user-123-name

    en sık sanal dizin yapısını simüle etmek için RewriteRules görüyoruz. Ama ahlaksız olmak zorunda değilsin. Segmentleme veya yapı için - tire de kullanabilirsiniz.

     RewriteRule ^user-(\d+)$    show.php?what=user&id=
     #                   └──────────────────────────────┘
     # This could use `(\w+)` alternatively for user names instead of ids.
    

    için de ortak /wiki:section:Page_Name düzeni:

     RewriteRule ^wiki:(\w+):(\w+)$  wiki.php?sect=&page= 
     #                   └─────┼────────────────────┘       │
     #                         └────────────────────────────┘
    

    , / - sınırlayıcılar ve : veya . arasında aynı kuralda bile alternatif olarak uygundur. Ya da farklı komut dosyaları üzerine varyantları eşlemek için tekrar iki RewriteRules var.

  • isteğe bağlı sondaki / eğik çizgi

    /dir = /dir/

    dizin stili yolları seçerken, bir final ile ve olmadan erişilebilir hale getirebilirsiniz /

     RewriteRule ^blog/([\w-]+)/?$  blog/show.php?id=
     #                         ┗┛
    

    Şimdi bu http://example.com/blog/123 ve /blog/123/ hem de işler . Ve /?$ yaklaşımı başka bir RewriteRule üzerine eklemek kolaydır.

  • esnek sanal yollar için segmentler

    .*/.*/.*/.*

    tek tek get parametrelerine /…/ kaynak yolu segmentlerinin kısıtlı bir kümesiyle karşılaşacağınız çoğu kural. Bazı komut dosyaları ancak seçenekleri değişken sayıda işlemek. Apache regexp motoru, keyfi sayıda optionalizing izin vermez. Ancak, kendiniz için bir kural bloğuna kolayca genişletebilirsiniz:

     Rewriterule ^(\w+)/?$                in.php?a=
     Rewriterule ^(\w+)/(\w+)/?$          in.php?a=&b=
     Rewriterule ^(\w+)/(\w+)/(\w+)/?$    in.php?a=&b=&c=
     #              └─────┴─────┴───────────────────┴────┴────┘
    

    beş yol parçasına ihtiyacınız varsa, bu şemayı beş kural halinde kopyalayın. Elbette her biri daha spesifik bir [^/]+ yer tutucu kullanabilirsiniz. Burada sipariş, örtüşmediği kadar önemli değildir. Bu yüzden ilk önce en sık kullanılan yollara sahip olmak iyidir.

    alternatif olarak, ?p[]=&p[]=&p[]=3 sorgu dizesiyle PHPs dizi parametrelerini buradan kullanabilirsiniz - komut dosyanız yalnızca önceden bölünmeyi tercih ederse. (Gerçi sadece daha yaygın catch-all kuralını kullanın ve komut dosyasının kendisini request_urı'den segmentleri genişletmesine izin verin.)

    Ayrıca bakınız: URL yol bölümlerimi sorgu dizesi anahtar değeri çiftlerine nasıl dönüştürebilirim?

  • isteğe bağlı segmentler

    prefix/opt?/.*

    ortak bir varyasyon içinde isteğe bağlı önekleri sahip olmaktır kural.

    : etrafında statik dizeleri veya daha kısıtlı tutucular varsa bu genellikle mantıklı
      RewriteRule ^(\w+)(?:/([^/]+))?/(\w+)$  ?main=&opt=&suffix=
    

    şimdi daha karmaşık desen (?:/([^/])+)? orada sadece bir sarar olmayan yakalama (?:…) grup, ve isteğe bağlı yapar )? . Yer alan yer tutucu ([^/]+) ikame deseni olurdu, ancak orta /…/ yolu yoksa boş olur.

  • kalanları yakalayın

    /prefix/123-capture/…/*/…whatever…

    Daha önce de belirtildiği gibi

    , sık sık çok genel yeniden yazma desenleri istemiyorum. Bununla birlikte, statik ve spesifik karşılaştırmaları bazen .* ile birleştirmek mantıklı değildir.

     RewriteRule ^(specific)/prefix/(\d+)(/.*)?$  speci.php?id=&otherparams=
    

    bu seçenek, herhangi bir /…/…/… sondaki yol segmentleri. Hangi o zaman tabii ki işleme gerektirir onları bölmek için komut dosyası ve variabl-ify ayıklanan parametreler kendisi ( Web-"MVC" çerçeveleri).

  • Trailing file "uzantıları"

    /old/path.HTML

    URL'leri gerçekten dosya uzantılarına sahip değil. Bu tüm referansın neyle ilgili olduğu (=URL'ler sanal konumlandırıcılardır, mutlaka bir doğrudan dosya sistemi görüntüsü). Bununla birlikte, daha önce 1:1 Dosya eşlemeniz varsa, daha basit kurallar oluşturabilir:

     RewriteRule  ^styles/([\w\.\-]+)\.css$  sass-cache.php?old_fn_base=
     RewriteRule  ^images/([\w\.\-]+)\.gif$  png-converter.php?load_from=
    

    diğer ortak kullanımlar eski .html yollarını yeni .php işleyicilerine yeniden eşleştiriyor veya yalnızca tek tek (gerçek/gerçek) dosyalar için dizin adlarını aliasing.

  • Ping-Pong (yönlendirmeler ve unison yeniden yazarları)

    /ugly.html ←→ /pretty

    yani bir noktada tarafından özetlenen olarak, sadece güzel bağlantıları taşımak için HTML sayfalarınızı yeniden yazıyorsunuz . Bu arada hala eski yolları için istekleri alırsınız, hatta bazen imleri. geçici çözüm olarak , ping-pong tarayıcıları görüntülemek/kurmak için yeni URL'ler.

    Bu ortak hile, gelen bir URL eskimiş / çirkin adlandırma şemasını takip ettiğinde 30x/konum yönlendirme göndermeyi içerir. Tarayıcılar daha sonra rerequest yeni/güzel URL, daha sonra orijinal veya yeni konuma (sadece DAHİLİ olarak) yeniden yazılır.

     # redirect browser for old/ugly incoming paths
     RewriteRule ^old/teams\.html$ /teams [R=301,QSA,END]
    
     # internally remap already-pretty incoming request
     RewriteRule ^teams$ teams.php        [QSA,END]
    

    bu örnekte [END] yerine [L] güvenli bir şekilde değiştirmek için nasıl kullanıldığını not edin. Eski Apache 2.2 sürümleri için kullanabilirsiniz diğer geçici çözümler, ayrıca yeniden eşleme örneğin sorgu dize parametreleri: çirkin güzel URL'ye yönlendirin, çirkin yola geri dönün, sonsuz döngüler olmadan

  • desenler

    /this+that+

    tarayıcı Adres çubuklarında değil değil, ancak şunları yapabilirsiniz Url'lerde boşluk kullanın. Yeniden yazma desenleri için ters eğik çizgi-kaçan \␣ boşluk kullanın. Else just " - alıntı tüm desen veya ikame:

     RewriteRule  "^this [\w ]+/(.*)$"  "index.php?id="  [L]
    

    istemcileri + veya %20 ile URL'leri seri hale getirir. Yine de Rewriterules'da, tüm göreli yol segmentleri için değişmez değer karakterlerle yorumlanır.

sık çoğaltır:

' .htaccess tuzaklar

şimdi bunu bir tuz tanesi ile alın. Her öneri tüm bağlamlara genelleştirilemez.

: bu tanınmış ve birkaç göze batmayan engellerin sadece basit bir özetidir
  • mod_rewrite ve .htaccess

    aslında gereken dizin başına yapılandırma dosyaları RewriteRules kullanmak için:

    • sunucunuzun AllowOverride All etkin olduğunu kontrol edin . Aksi takdirde dizin başına .htaccess yönergeleriniz göz ardı edilecek ve RewriteRules çalışmaz.

    • ' var mod_rewrite etkin httpd.conf modülleri bölümü.

    • , RewriteEngine On ile her kural listesini hazırladı. Mod_rewrite <VirtualHost> ve <Directory> da aktiftir., dizin başına .htaccess dosyaları ayrı ayrı çağırılmalıdır.

  • önde gelen çizgi ^/

    ile eşleşmeyecek

    sen başlamak gerekir .htaccess ile rewriterule desenleri ^/ normalde:

     RewriteRule ^/article/\d+$  …
                  ↑
    

    bu genellikle eski öğreticiler görülür. Ve Eski Apache 1 için doğru olurdu.x sürümleri. Günümüzde istek yolları , dizin- .htaccess RewriteRules. Sadece / önde gelen bırakın.

    * önde gelen eğik çizginin hala doğru olduğunu unutmayın <VirtualHost> bölümleri olsa da. Bu nedenle, kural paritesi için ^/? seçeneğini sıklıkla görüyorsunuz.

    * Veya RewriteCond %{REQUEST_URI} kullanırken hala önde gelen / ile eşleşirsiniz .

    * Ayrıca Bkz Webmaster.SE: mod_rewrite desenlerinde lider eğik çizgi (/) ne zaman gereklidir?

  • <IfModule *> sarmalayıcılar begone!

    muhtemelen bunu birçok örnekte gördü:

    <IfModule mod_rewrite.c>
       Rewrite… 
    </IfModule>
    
    • bu yapar mantıklı <VirtualHost> bölümleri-böyle ScriptAliasMatch gibi başka bir geri dönüş seçeneği ile kombine edildi. (Ama kimse bunu yapmaz).
    • ve yaygın birçok açık kaynak projeleri ile varsayılan .htaccess rulesets için dağıtılır. Orada sadece geri dönüş olarak kastediliyor ve" çirkin " URL'leri varsayılan olarak çalışıyor.

    ancak istemiyorum genellikle kendi .htaccess dosyaları.

    • öncelikle, mod_rewrite rastgele devre dışı bırakmaz. (Eğer olsaydı, daha büyük sorunlarınız olurdu).
    • gerçekten devre dışı bırakılmış olsaydı, RewriteRules yine de işe yaramadı.
    • HTTP 500 hatalarını önlemek içindir. Ne genellikle gerçekleştirir kullanıcılarınızı bunun yerine http 404 hataları ile inceliyor. (Değil çok bunu düşünüyorsanız daha kullanıcı dostu.)
    • pratik olarak daha kullanışlı günlük girdileri veya sunucu bildirim postaları bastırır. ve , Rewriterüllerin neden asla çalışmadığı konusunda olursunuz.

    genelleştirilmiş koruma olarak cazip görünen şey, genellikle bir uygulamada engel.

  • RewriteBase kullanma

    birçok kopya + yapıştırma örnekleri RewriteBase / yönergesi içerir. Bu da zaten örtülü varsayılan olur. Yani buna ihtiyacın yok. Fantezi VirtualHost yeniden yazma şemaları için bir geçici çözüm ve bazı paylaşılan barınaklar için yanlış DOCUMENT_ROOT yolları.

    ile kullanmak mantıklı daha derin alt dizinlerde bireysel web uygulamaları. Bu gibi durumlarda RewriteRule kalıplarını kısaltabilir. Genellikle, dizin başına kural kümelerinde göreli yol belirticileri tercih etmek en iyisidir.

    Ayrıca Bkz. RewriteBase nasıl çalışır.htaccess

  • Devre Dışı Bırakma MultiViews sanal yollar çakıştığında

    URL yeniden yazma öncelikle desteklemek için kullanılır sanal gelen yolları. Genellikle sadece bir dağıtıcı komut dosyası ( index.php ) veya birkaç bireysel işleyiciniz var( articles.php , blog.php , wiki.php , ...). İkincisi , benzer sanal RewriteRule yollarıyla çakışabilir.

    /article/123 için bir istek, örneğin article.php ile /123 PATH_INFO örtülü olarak eşleştirilebilir. Kurallarınızı korumak zorunda kalacaksınız. sıradan RewriteCond !-f + !-d , ve / veya PATH_INFO desteğini devre dışı bırakın, ya da belki de Options -MultiViews devre dışı bırakın .

    her zaman söylemek değil zorunda . İçerik müzakere sanal kaynaklara sadece bir otomatizm olduğunu.

  • sipariş önemlidir

    bkz. mod_rewrite hakkında bilmek istediğiniz her şey zaten yapmadıysanız. Birden çok Rewriterülün birleştirilmesi genellikle etkileşime neden olur. Bu [L] bayrağı başına alışkanlıkla önlemek için bir şey değil, ama bir kez usta kucaklamak olacak bir şema. can re-re-re write sanal yolları bir kuraldan diğerine, gerçek bir hedef işleyiciye ulaşana kadar.

    hala sık sık en özel kurallara sahip olmak istiyorum (sabit dize /forum/… desenleri, veya daha kısıtlayıcı tutucular [^/.]+ ) erken kuralları. Genel slurp - tüm kurallar ( .* ) daha iyi daha sonra olanlar için bırakılır. (Bir istisna, birincil blok olarak RewriteCond -f/-d koruyucusudur.)

  • stil sayfaları ve görüntüler

    çalışmayı durdurur

    sanal dizin yapıları /blog/article/123 tanıtmak zaman bu HTML ( <img src=mouse.png> gibi) göreli kaynak başvuruları etkiler. Hangi tarafından çözülebilir:

    • sadece sunucu-mutlak referanslar kullanarak href="/old.html" veya src="/logo.png"
    • genellikle <base href="/index"> HTML <head> bölümüne ekleyerek. Bu, daha önce oldukları şeylere göreli referansları dolaylı olarak yeniden bildirir.

    alternatif olarak daha fazla RewriteRules hazırlayabilirsiniz rebind .css veya .png yolları orijinal konumlarına. Ancak bu hem gereksiz hem de ekstra yönlendirmeler oluşturur ve önbelleğe almayı engeller.

    Ayrıca bakınız: CSS, JS ve görüntüler güzel url ile görünmüyor

  • RewriteConds just mask one RewriteRule

    ortak bir uyumsuzluk, bir Rewritecond'un birden fazla Rewriterülünü (çünkü onlar görsel birlikte düzenlenmiş):

     RewriteCond %{SERVER_NAME} localhost
     RewriteRule ^secret  admin/tools.php
     RewriteRule ^hidden  sqladmin.cgi
    

    varsayılan olarak değil. bayrağını kullanarak [S=2] zincirleyebilirsiniz. Yoksa tekrarlamak zorundasın. Bazen yeniden yazma işlemi erken [END] için bir "ters" birincil kural zanaat olabilir iken.

  • Query_string rewriterules muaf

    RewriteRule index.php\?x=y ile eşleşemezsiniz , çünkü mod_rewrite sadece varsayılan başına göreli yolları karşılaştırır. Bununla birlikte, bunları ayrı ayrı eşleştirebilirsiniz:

     RewriteCond %{QUERY_STRING} \b(?:param)=([^&]+)(?:&|$)
     RewriteRule ^add/(.+)$  add/%1/  # ←──﹪₁──┘
    

    Ayrıca Bkz. sorgu dize değişkenlerini mod_rewrite ile nasıl eşleştirebilirim?

  • .htaccess vs. <VirtualHost>

    dizin başına yapılandırma dosyasında RewriteRules kullanıyorsanız, regex performansı hakkında endişelenmek anlamsızdır. Apache! derliyordu Ortak bir yönlendirme çerçevesi ile bir PHP sürecinden daha uzun pcre desenleri. Yüksek trafik siteleri için ancak dikkate almalısınız savaş test edildikten sonra, kuralları vhost sunucu yapılandırmasına taşımak.

    bu durumda, ^/? dizin ayırıcı öneki optionalized tercih. Bu PerDir ve sunucu arasında serbestçe RewriteRules taşımak için izin verir yapılandırma dosyaları.

  • 'bir şey çalışmıyor

    Fret değil.

    • karşılaştırmak access.log and error.log

      genellikle error.log ve access.log bakarak nasıl bir RewriteRule misbehaves anlamaya. Hangi istek yolunun başlangıçta geldiğini görmek için erişim sürelerini ilişkilendirin ve hangi yol/dosya Apache'nin çözemediği (hata 404/500).

      bu, hangi RewriteRule suçlu olduğunu söylemiyor. Ancak /docroot/21-.itle?index.php gibi ulaşılmaz son yollar, daha fazla nerede inceleneceğini verebilir. Aksi takdirde bazı öngörülebilir yollar elde edene kadar kuralları devre dışı bırakın.

    • yeniden yazmayı etkinleştir

      bkz. Apache RewriteLog dokümanlar. Hata ayıklama için vhost bölümlerinde etkinleştirebilirsiniz:

      # Apache 2.2
      RewriteLogLevel 5
      RewriteLog /tmp/rewrite.log
      
      # Apache 2.4
      LogLevel alert rewrite:trace5
      #ErrorLog /tmp/rewrite.log
      

      , gelen istek yollarının her kural tarafından nasıl değiştirileceğinin ayrıntılı bir özetini verir:

      [..] applying pattern '^test_.*$' to uri 'index.php'
      [..] strip per-dir prefix: /srv/www/vhosts/hc-profi/index.php -> index.php
      [..] applying pattern '^index\.php$' to uri 'index.php'
      

      aşırı genel kuralları ve regex aksilik daraltmak için yardımcı olur.

      Ayrıca bakınız:

      * .htaccess çalışmıyor (mod_rewrite)

      * hata ayıklama için ipuçları.htaccess yeniden yazma kuralları

    • kendi soru sormadan önce

      bildiğiniz gibi, yığın taşması mod_rewrite hakkında sorular sormak için çok uygundur. Onları on-topic yapın önceki araştırma ve girişimleri (gereksiz cevapları önlemek) dahil ederek, temel göstermek anlayış, ve:

      • dahil tam giriş URL'leri örnekleri, yanlış yazılmış hedef yolları, gerçek dizin yapısı.
      • komple RewriteRule seti, ancak ayrıca Varsayılanı arızalı olanı ayırır.
      • Apache ve PHP sürümleri, OS tipi, dosya sistemi, DOCUMENT_ROOT ve PHPs $_SERVER ortamı bir parametre uyumsuzluğu ile ilgili ise.
      • senin access.log bir alıntı ve error.log mevcut kuralların çözüldüğünü doğrulamak için. Daha da iyisi, rewrite.log özeti.

      bu, daha hızlı ve daha kesin cevaplar verir ve onları başkalarına daha kullanışlı hale getirir.

  • yorum senin .htaccess

    bir yerden örnekler kopyalarsanız, # comment and origin link eklemeyi unutmayın . İhmal etmek sadece kötü davranış olsa da atıf, genellikle gerçekten daha sonra bakım acıyor. Herhangi bir kod veya öğretici kaynağı belgeleyin. Özellikle unversed iken olmalıdır sihirli kara kutular gibi davranmamakla daha çok ilgileniyorlar.

  • "SEO" değil -

    URL'leri

    Yasal Uyarı: sadece bir evcil hayvan peeve. sık sık "SEO" bağlantılar ya da bir şey olarak adlandırılan güzel URL yeniden yazma şemaları duymak. Bu googling için yararlı iken örnekler, bu tarihli bir yanlış isim.

    modern arama motorlarının hiçbiri gerçekten .html ve .php yol segmentlerinde veya ?id=123 sorgu dizeleri tarafından rahatsız. AltaVista gibi eski arama motorları, , potansiyel olarak zararlı erişim yolları ile web sitelerini tarama kaçının. Modern tarayıcılar genellikle derin web kaynakları için özlem bile vardır.

    ne "güzel" URL'ler gerekir kavramsal olarak kullanıcı dostu web siteleri yapmak için kullanılabilir .

    1. okunabilir ve bariz kaynak şemaları sahip.
    2. ' URL'ler uzun ömürlüdür ( kalıcı bağlantılar ).
    3. /common/tree/nesting ile keşfedilebilirlik sağlar .

    ancak için benzersiz gereksinimleri feda etmeyin konformizm.

Araçlar

çoğu get-parameterish URL'leri için RewriteRules oluşturmak için çeşitli çevrimiçi araçlar vardır:

çoğunlukla sadece [^/]+ genel tutucular çıktı, ancak önemsiz siteler için büyük olasılıkla yeterlidir.

35
cevap mario 2017-05-23 15:10:30
kaynak

mod_rewrite

alternatifleri

birçok temel sanal URL şemaları RewriteRules kullanmadan elde edilebilir. Apache, PHP komut dosyalarının .php uzantısı olmadan ve sanal PATH_INFO argümanı ile çağrılmasına izin verir.

  1. PATH_INFO , Luke

    kullanın

    ' AcceptPathInfo On genellikle varsayılan olarak etkindir. Hangisi?

    ve diğer kaynak Url'lerinin sanal bir bağımsız değişkeni taşımasına izin verir:

    http://example.com/script.php/virtual/path
    

    Şimdi bu /virtual/path , PHP'DE $_SERVER["PATH_INFO"] olarak görünür ve istediğiniz herhangi bir ekstra argümanı ele alabilirsiniz.

    bu, Apache ayrı giriş yolu segmentlerine sahip olmak kadar uygun değildir , , ve onları PHP'YE farklı $_GET değişkenleri olarak geçiriyoruz. Sadece taklit ediyor daha az yapılandırma çabasıyla "güzel URL'ler".

  2. etkinleştirmek MultiViews gizlemek için .php uzantısı

    Url'lerdeki .php "dosya uzantıları" ndan kaçınmanın en basit seçeneği şu şekildedir:

    Options +MultiViews
    

    bu, eşleşen basename nedeniyle /article HTTP istekleri için article.php seçin Apache vardır. Ve bu ile birlikte iyi çalışır yukarıda belirtilen PATH_INFO özelliği. Böylece http://example.com/article/virtual/title gibi URL'leri kullanabilirsiniz. Birden PHP çağırma noktaları/komut dosyaları ile geleneksel bir Web uygulaması varsa mantıklı.

    , multiviews'in farklı/daha geniş bir amaca sahip olduğunu unutmayın. Apache her zaman eşleşen basenames ile diğer dosyaları arar, çünkü bir çok küçük performans cezası incurs. Aslında içerik müzakere içindir, bu yüzden tarayıcılar mevcut kaynaklar arasında en iyi alternatif (örneğin article.en.php , article.fr.php , article.jp.mp4 ).

  3. extensionless için SetType veya SetHandler .php '

    Url'lerdeki .php soneklerini taşımaktan kaçınmak için daha yönlendirilmiş bir yaklaşım diğer dosya şemaları için PHP işleyicisini yapılandırmaktır. En basit seçenek varsayılan MIME/işleyici türünü geçersiz kılmaktır via .htaccess :

    DefaultType application/x-httpd-php
    

    bu şekilde article.php komut dosyanızı sadece article (uzantı olmadan) olarak yeniden adlandırabilirsiniz, ancak yine de PHP komut dosyası olarak işlenir.

    Şimdi bu bazı güvenlik ve performans etkileri olabilir, çünkü tüm extensionless dosyaları şimdi PHP aracılığıyla borulu olacaktır. Bu nedenle, yalnızca tek tek dosyalar için bu davranışı alternatif olarak ayarlayabilirsiniz:

    <Files article>
      SetHandler application/x-httpd-php
      # or SetType 
    </Files>
    

    bu sunucu kurulum ve kullanılan PHP sapı biraz bağımlı. Ortak alternatifler ForceType application/x-httpd-php veya AddHandler php5-script içerir .

    yine bu tür ayarların bir .htaccess dan alt klasörlere yayıldığını unutmayın. Her zaman komut dosyası yürütülmesini ( SetHandler None ve Options -Exec veya php_flag engine off vb.) devre dışı bırakmalısınız.) statik kaynaklar için, ve upload / dizinleri vb.

  4. Diğer Modeller yeniden yazma şemaları

    birçok seçenek arasında, Apache mod_alias özellikleri - bazen mod_rewrite S RewriteRules yanı sıra çalışır. Bunların çoğunun, dizin başına .htaccess yapılandırma dosyalarında değil, <VirtualHost> bölümünde ayarlanması gerektiğini unutmayın.

    • ScriptAliasMatch öncelikle CGI betikleri için değil, aynı zamanda PHP için de çalışıyor. Sadece gibi regexps sağlar herhangi bir RewriteRule . Aslında belki de bir catch-all ön denetleyicisini yapılandırmanın en sağlam seçeneği.

    • ve düz Alias birkaç basit yeniden yazma şemaları ile de yardımcı olur.

    • düz bir ErrorDocument yönergesi, bir PHP betiğinin sanal yolları ele almasına izin vermek için kullanılabilir. Bununla birlikte, bunun bir kludgy geçici çözüm olduğunu unutmayın, istekleri almaktan başka bir şey yasaklar ve hatayı seller.tanım gereği oturum açın.

    bkz. http://httpd.apache.org/docs/2.2/urlmapping.html daha fazla ipucu için .

5
cevap mario 2017-05-23 15:34:36
kaynak