.htaccess met optioneel deel/directory

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • SvMp
  • Registratie: September 2000
  • Niet online
Voor een meertalige website wil ik dit soort URLs: www.website.xyz/<locale>/content/45
De locale kan enkel een taal zijn (nl, fr, etc..) of een volledige lokale (nl_NL, nl_BE, fr_BE, etc.).

Naast /content zijn er nog een stuk of 10 mogelijkheden.

Op Got en via Google genoeg te vinden over hoe je dit in .htaccess plaatst. Er zoveel locales dat ik het valideren van de locale door PHP laat doen.

Het is echter ook mogelijk om de site te bezoeken via: www.website.xyz/content/45.
In dat geval wordt de locale gedetecteerd, er wordt verder niet doorverwezen naar een URL met locale. Een URL zonder locale levert autodetectie op en volstaat voor de meeste bezoekers. Een URL met locale is vooral voor links waarin de locale expliciet gekozen wordt.

Dit betekent dus dat het gedeelte <locale> dus leeg kan zijn.
Hoe doe ik dat in .htaccess? Niets over kunnen vinden.

Volgens mij zijn er 3 opties:

1. Volledig door PHP laten afhandelen
www.website.xyz/*/* -> index.php?locale=$1&page=$2
www.website.xyz/* -> index.php?page=$2

Heeft niet mijn voorkeur, er zijn ook URLs met méér niveaus en andere get-vars.

2. Alle onderdelen dubbel
www.website.xyz/*/content -> index.php?locale=$1&page=content
www.website.xyz/content -> index.php?page=content
www.website.xyz/*/admin -> index.php?locale=$1&page=content
www.website.xyz/admin -> index.php?page=content
etc..

3. Elk onder deel slechts één keer. Dit heeft mijn voorkeur!
Maar hoe doe ik dat?

[ Voor 3% gewijzigd door SvMp op 22-01-2012 12:38 ]


Acties:
  • 0 Henk 'm!

Verwijderd

SvMp schreef op zondag 22 januari 2012 @ 12:36:

Het is echter ook mogelijk om de site te bezoeken via: www.website.xyz/content/45.
In dat geval wordt de locale gedetecteerd, er wordt verder niet doorverwezen naar een URL met locale.
Waarom niet? En waarom is het überhaupt mogelijk de site via zo'n URL te bezoeken? Een taalspecifieke pagina zal hopelijk alleen links bevatten naar artikelen in dezelfde taal, en niet naar een soort autodetectie.

URL's horen unieke content op te leveren, vandaar de naam. Als een URL voor de ene gebruiker andere content kan opleveren dan voor de andere, heb je bij deze niet meer het recht om te klagen over alles dat met zoekmachines te maken heeft.
Dit betekent dus dat het gedeelte <locale> dus leeg kan zijn.
Hoe doe ik dat in .htaccess? Niets over kunnen vinden.
Er is maar één goede optie, en dat is om één RewriteRule te maken die alles naar één script stuurt. Dat script kan de URL wel analyseren. Je scripts moet URL's kunnen bouwen? Dan dus ook kunnen ontleden.

Acties:
  • 0 Henk 'm!

  • Joolee
  • Registratie: Juni 2005
  • Niet online
Gewoon domein.nl/* doorverwijzen naar index.php. Dan via de juiste $_SERVER variabele het opgevraagde pad achterhalen en in PHP de juiste betekenis erachter vinden. Bij requests als domein.nl/nl/zoeken?q=zoekterm parsed PHP zelf nog steeds netjes de get paramters waardoor je $_GET['q'] kunt gebruiken zoals het hoort.

Je zult in alle situaties wel met een rewritecond ervoor moeten zorgen dat aanvragen voor bestanden die echt bestaan (-f) en eventueel mappen die echt bestaan (-d) niet worden doorgestuurd naar index.php maar genegeerd worden door je rewrite rule.

[ Voor 13% gewijzigd door Joolee op 22-01-2012 12:50 ]


Acties:
  • 0 Henk 'm!

  • Miyamoto
  • Registratie: Februari 2009
  • Laatst online: 09:00
Uhm, hoe ziet je htaccess er nu uit? Zoals Cheatah aangeeft, moet je sowieso eens overwegen of je wel een url zonder locale wilt. Maar ben wel benieuwd wat je nu als htaccess hebt, daar het toevoegen van condities op bepaalde strings niet heel lastig is. Er zijn meer operators dan '*'.

Cheatah, Joolee: Als het aantal mogelijkheden (van 'content') beperkt is, waarom dan alles doorsturen naar één pagina?

[ Voor 19% gewijzigd door Miyamoto op 22-01-2012 12:56 ]


Acties:
  • 0 Henk 'm!

  • SvMp
  • Registratie: September 2000
  • Niet online
Die * is geen operator, maar een soort pseudocode.

Acties:
  • 0 Henk 'm!

Verwijderd

Miyamoto schreef op zondag 22 januari 2012 @ 12:55:

Cheatah, Joolee: Als het aantal mogelijkheden (van 'content') beperkt is, waarom dan alles doorsturen naar één pagina?
Waarom doorverwijzen naar meerdere scripts als het op één achterliggend framework draait?

Als je een forum hebt dat door softwareleverancier A is gemaakt, en een blog door softwareleverancier B, dan vind ik het een ander verhaal.

Vergeet even dat een PHP script een pagina is. Dat is niet zo.

Acties:
  • 0 Henk 'm!

  • Miyamoto
  • Registratie: Februari 2009
  • Laatst online: 09:00
SvMp schreef op zondag 22 januari 2012 @ 13:00:
Die * is geen operator, maar een soort pseudocode.
Maar die is geheim? ;)
Verwijderd schreef op zondag 22 januari 2012 @ 13:03:
[...]

Waarom doorverwijzen naar meerdere scripts als het op één achterliggend framework draait?

Als je een forum hebt dat door softwareleverancier A is gemaakt, en een blog door softwareleverancier B, dan vind ik het een ander verhaal.

Vergeet even dat een PHP script een pagina is. Dat is niet zo.
Weet ik, maar dat kon/kan ik niet opmaken uit de startpost.
Als het achterliggende framework blijkbaar alle info heeft, heb je gelijk en kun je beter alles redirecten naar dat script. Dat is optie 1 van TS, maar die voldoet blijkbaar niet.

Acties:
  • 0 Henk 'm!

  • SvMp
  • Registratie: September 2000
  • Niet online
Er is één index.php, het enige PHP bestand dat in de webroot staat.
Ik redirect liever niet alles naar het script in één rewrite, omdat mijn voorkeur uit gaat naar een pakketje $_GET-variabelen.

[ Voor 18% gewijzigd door SvMp op 22-01-2012 14:33 ]


Acties:
  • 0 Henk 'm!

  • Miyamoto
  • Registratie: Februari 2009
  • Laatst online: 09:00
Als je optie 2 werkend hebt, ben je waarschijnlijk slechts 1 karakter van optie 3 verwijderd...
Vandaar dat ik nogal nieuwsgierig ben (was misschien niet duidelijk) naar hetgeen je nu hebt en wat je dan hebt geprobeerd.

Een zoekopdracht in Google naar 'htaccess rewrite' geeft me een aantal interessante quantifiers. Kun je daar iets mee?

Acties:
  • 0 Henk 'm!

  • SvMp
  • Registratie: September 2000
  • Niet online
Een schop van dit oude topic, ik heb inmiddels een oplossing. Alleen niet helemaal bevredigend.

Mijn .htaccess:
code:
1
2
3
4
5
6
RewriteEngine On
Options +FollowSymlinks
RewriteBase /

RewriteRule ^(nl|en|de|fr)(|/.*)$ $2?locale=$1 [NC,L]
RewriteRule ^customer/?$ index.php?page=customer [L,QSA,NC]


/customers geeft een get-var 'page' met waarde 'customers', maar GET['locale'] is niet gedefinieerd.
/de/customers, /nl/customers, etc.. definieert GET['locale'] wel.

Alleen dat ene regeltje volstaat voor talen/locales.

Maar..
/de/nl/fr/customers werkt ook!
/nl/nl/customers
etc..

Dat is ongewenst. Die taal mag uiteraard maar één keer.

Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 09:51
Ik doe meestal zoiets:
code:
1
2
3
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

Dus als de pagina niet al bestaat, doorverwijzen naar index.php
En dan zoiets in index.php
PHP:
1
2
3
$reqUrl = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
$reqParams = explode('/', $reqUrl);
list($locale, $page) = $reqParams;

Dus alls gaat naar index.php, daar bekijk je wat de string is, parse_url zorgt er voor dat je de paramaters weglaat, en de trim haalt de beginnende/laatste / weg. Dan exploden en je hebt je parameters op volgorde staan.
Dan kan je kijken of $locale een van je gebruikte locales is, en anders dus de variabelen op een andere manier listen. (Of eerst even kijken naar $reqParams[0])
(Misschien niet de oplossing die je wil, maar zorgt er wel voor dat je niet alles in je .htaccess moet gaan bedenken, en ik merk dat het vaak makkelijker is om gewoon te zorgen dat je de locale altijd meegeeft, ook voor google, maar ook omdat het gewoon simpeler is)

Acties:
  • 0 Henk 'm!

Verwijderd

SvMp schreef op donderdag 03 mei 2012 @ 13:46:
Een schop van dit oude topic, ik heb inmiddels een oplossing. Alleen niet helemaal bevredigend.

Mijn .htaccess:
code:
1
2
3
4
5
6
RewriteEngine On
Options +FollowSymlinks
RewriteBase /

RewriteRule ^(nl|en|de|fr)(|/.*)$ $2?locale=$1 [NC,L]
RewriteRule ^customer/?$ index.php?page=customer [L,QSA,NC]


/customers geeft een get-var 'page' met waarde 'customers', maar GET['locale'] is niet gedefinieerd.
/de/customers, /nl/customers, etc.. definieert GET['locale'] wel.

Alleen dat ene regeltje volstaat voor talen/locales.

Maar..
/de/nl/fr/customers werkt ook!
/nl/nl/customers
etc..

Dat is ongewenst. Die taal mag uiteraard maar één keer.
Je geeft ook aan in je regex dat je alles accepteerd dus ook /en maar ook /en/adfdgsdgsdgssdg/customer:
code:
1
(|/.*)


Dit kun je heel simpel oplossen, iets wat ik niet voor ga kauwen. Daarnaast vind ik wel dat je de verkeerde aanpak gebruikt. Wat als:
  • Je een nieuwe taal wil toevoegen
  • Je een diepere gelaagdheid hebt: customer/overview/edit
Ik zou zeggen, lees het topic nog even goed en kijk naar de tips die gegeven worden. :)

Tip: Als je je expressie even wilt testen: http://www.regextester.com/

Acties:
  • 0 Henk 'm!

  • SvMp
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op donderdag 03 mei 2012 @ 14:46:
[...]

Je geeft ook aan in je regex dat je alles accepteerd dus ook /en maar ook /en/adfdgsdgsdgssdg/customer:
code:
1
(|/.*)
Nee hoor, dat wordt niet geaccepteerd.

(|/.*) betekent eventueel een slash aan het eind, zonder dat dit verplicht is. Als ik |/ vervang door /? dan krijg je dat /nlcustomers ook werkt.

Volgens mij ontstaat het probleem niet door een foute regex, maar door het gedrag van mod_rewrite: Na het toepassen van de eerste rewrite, gaat mod_rewrite de eerste regel opnieuw evalueren in plaats van verder te gaan met de volgende.

[ Voor 21% gewijzigd door SvMp op 03-05-2012 15:47 ]


Acties:
  • 0 Henk 'm!

Verwijderd

SvMp schreef op donderdag 03 mei 2012 @ 15:45:
[...]


Nee hoor, dat wordt niet geaccepteerd.

(|/.*) betekent eventueel een slash aan het eind, zonder dat dit verplicht is. Als ik |/ vervang door /? dan krijg je dat /nlcustomers ook werkt.

Volgens mij ontstaat het probleem niet door een foute regex, maar door het gedrag van mod_rewrite: Na het toepassen van de eerste rewrite, gaat mod_rewrite de eerste regel opnieuw evalueren in plaats van verder te gaan met de volgende.
Ok dan werkt htaccess rewrite anders dan de regex van perl(ik had hem even getest namelijk). '.' betekent daar namelijk dat alle tekens geaccepteerd worden en * dat het er 0 of meer kunnen zijn. Dit zou betekenen dat / ook geaccepteerd wordt.

Wordt je wel naar de goede url ge-route als je nummer twee uitzet?

Acties:
  • 0 Henk 'm!

  • SvMp
  • Registratie: September 2000
  • Niet online
Met "nummer twee" bedoel je die tweede rule?
Ja. /, /nl, /de, etc.. werkt goed. Alleen /customer of /<lang>/customer geeft een 404 maar dat is ook de bedoeling als er geen rule voor aanwezig is.

[ Voor 20% gewijzigd door SvMp op 03-05-2012 16:14 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Ik weet niet wat je configuratie is, maar ik heb het even getest bij mij, en het werkt prima:
code:
1
2
3
'QUERY_STRING' => string 'page=customer&locale=en' (length=23)
  'REQUEST_URI' => string '/en/customer' (length=12)
  'SCRIPT_NAME' => string '/index.php' (length=10)

Acties:
  • 0 Henk 'm!

  • SvMp
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op donderdag 03 mei 2012 @ 16:50:
Ik weet niet wat je configuratie is, maar ik heb het even getest bij mij, en het werkt prima:
code:
1
2
3
'QUERY_STRING' => string 'page=customer&locale=en' (length=23)
  'REQUEST_URI' => string '/en/customer' (length=12)
  'SCRIPT_NAME' => string '/index.php' (length=10)
Bij mij ook.
Alleen '/en/nl/customer' werkt óók en dat is het probleem. Die hoort een 404 te geven.
Net zoals /nl/nl, /nl/de/customer etc..

Acties:
  • 0 Henk 'm!

Verwijderd

Dat bedoelde ik ook met je huidige regexs...
Ok dan werkt htaccess rewrite anders dan de regex van perl(ik had hem even getest namelijk). '.' betekent daar namelijk dat alle tekens geaccepteerd worden en * dat het er 0 of meer kunnen zijn. Dit zou betekenen dat / ook geaccepteerd wordt.
code:
1
RewriteRule ^(nl|en|de|fr)(/([^/]+))?$ $3?locale=$1 [NC,L]


Ik zie het | symbool er trouwens niet tussen staan: http://httpd.apache.org/d.../rewrite/intro.html#regex :O

[ Voor 13% gewijzigd door Verwijderd op 03-05-2012 18:09 ]


Acties:
  • 0 Henk 'm!

  • SvMp
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op donderdag 03 mei 2012 @ 18:03:
Dat bedoelde ik ook met je huidige regexs...


[...]


code:
1
RewriteRule ^(nl|en|de|fr)(/([^/]+))?$ $3?locale=$1 [NC,L]


Ik zie het | symbool er trouwens niet tussen staan: http://httpd.apache.org/d.../rewrite/intro.html#regex :O
Deze rule werkt niet in combinatie met de tweede rule. Naast 'customer' komen er nog vele rules. De taal wil ik apart hebben, zodat ik die niet in elke rule hoef te verwerken. Maar juist daar laat mod_rewrite het afweten.

Is wat ik wil nou echt niet mogelijk?

Simpelweg een set rules waarbij ik /<taal>/<page> of /<page> kan laten werken, waarbij de taal in een afzonderlijke rule(s) wordt opgevangen.

Acties:
  • 0 Henk 'm!

Verwijderd

Dit werkt in mijn configuratie wel...
- OSX Lion
- Server version: Apache/2.2.21 (Unix).

http://local.local/en/customer
geeft:
code:
1
2
3
'QUERY_STRING' => string 'page=customer&locale=en' (length=23)
  'REQUEST_URI' => string '/en/customer' (length=12)
  'SCRIPT_NAME' => string '/index.php' (length=10)


http://local.local/en/en/customer
Geeft een 404

Na een 3e regel toegevoegd te hebben:
RewriteRule ^test/?$ index.php?page=test [L,QSA,NC]

Geeft de volgende url: http://local.local/en/test
code:
1
2
3
'QUERY_STRING' => string 'page=test&locale=en' (length=19)
  'REQUEST_URI' => string '/en/test' (length=8)
  'SCRIPT_NAME' => string '/index.php' (length=10)

Acties:
  • 0 Henk 'm!

  • azerty
  • Registratie: Maart 2009
  • Laatst online: 08:38
heb je http://local.local/customer ook al getest? :p

Acties:
  • 0 Henk 'm!

  • WouZz
  • Registratie: Mei 2000
  • Niet online

WouZz

Elvis is alive!

Zoals al gezegd: waarom nog rewriten naar GET parameters als je toch alles al naar een index.php herschrijft? Oftewel, herschrijf alles behalve static files naar je index.php. Bouw dan een mooi MVC laagje waarin je je path/GET/POST variabelen uit elkaar trekt, default, route etc. Daarna kan je altijd nog een nette 30x/403/404 oid header plus custom error page terug geven.

Framework anyone?

On track


Acties:
  • 0 Henk 'm!

  • SvMp
  • Registratie: September 2000
  • Niet online
Bedankt voor het meedenken allemaal!

@altrincham: Het werkt bij mij nu ook. Ik heb al jouw suggesties overgenomen. /nl/de/customer geeft netjes een 404 terwijl /nl/customer wel werkt. En het is uitbreidbaar, met bijvoorbeeld een /test.
Maar /nl/de werkt ook |:(

@WouZz: Mijn project draait op een eigen geschreven framework en het is een kleine moeite om jouw suggestie door te voeren. Ik heb dan echter het idee dat ik het werk van de webserver overneem. Dus het is niet een kwestie van niet kunnen, maar niet willen. Maar gezien het onbevredigende resultaat met mod_rewrite, zal het toch jouw suggestie worden.

Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 09:51
Hoezo het werk van de webserver overnemen? Jij wil je url's rewriten, dus jij zal het ook moeten fixen, of dat nu met regex regels in je htaccess bestand is, of via php ;)

Acties:
  • 0 Henk 'm!

  • WouZz
  • Registratie: Mei 2000
  • Niet online

WouZz

Elvis is alive!

SvMp schreef op vrijdag 04 mei 2012 @ 10:30:
Dus het is niet een kwestie van niet kunnen, maar niet willen. [...]
Ok, die begrijp ik. Maar je zou je misschien af kunnen vragen in welke rol je de web-server wilt plaatsen. Kijk, een standaard Apache serveert statische html (incl errorpages), maar kan ook authenticatie doen (en dat doet je framework zelf waarschijnlijk beter/anders). Apache heeft zelfs een FancyIndexes module, maar toch wil jij een mooi CMS bouwen. En er zijn genoeg voorbeelden te vinden van frameworks die zelf alle routing afhandelen. Kijk eens naar Drupal, WordPress etc., maar zeker ook op andere platforms als Java en RoR is het vaak standaard onderdeel van het framework. Waarom? Omdat je kan beargumenteren dat het gewoon onderdeel van je applicatie is, het flexibel moet zijn, configureerbaar en onderhoudbaar. En dan wat betreft performance, ja Apache zal dat op het eerste gezicht beter doen, scheelt weer db lookups etc. Maar ook daar zijn oplossingen voor te vinden, indien nodig.

On track

Pagina: 1