pagina achter slash in URL
Ik heb wellicht een hele simpele vraag. Ik wil graag voor een website een actie pagina aanmaken. Je ziet ze wel eens voorbijkomen in de trant van 'www.domein.nl/actie ' zonder enige extensie erachter.
En dat is tevens mijn vraag, hoe krijg ik het voor elkaar dat ik een pagina kan maken, zonder direct .html of .php er aan toe te voegen, dat mensen direct op de bedoelde actie pagina komen?
Bij voorbaat dank voor jullie reactie,
Met vriendelijke groet,
Timo
Edit:
Topictitel aangepast van 'actie pagina' naar 'pagina achter slash in URL'
Gewijzigd op 22/11/2018 19:58:37 door - Ariën -
TL;DR versie in het groen.
Wat er heel kort door de bocht moet gebeuren is het volgende: alle requests die naar jouw website worden gestuurd worden niet langer direct afgehandeld (omdat je rechtstreeks een PHP-script aanroept) maar het adres wordt eerst intern vertaald naar uit te voeren code, eventueel met extra parameters. Er vindt dus in feite een mapping van een externe URL naar een interne (applicatie-)URL plaats.
Een populaire manier om dit te doen is vaak door gebruikmaking van Apache's mod_rewrite module. Wat mensen dan vaak doen is *alles* mappen, oftewel, ze stellen een RewriteRule op (letterlijk een herschrijfregel van een externe naar een interne URL) voor ieder adres.
Dit wordt op den duur zeer bewerkelijk en foutgevoelig, en op een gegeven moment wordt dit ook een brei waarin de volgorde van deze RewriteRules een belangrijke rol gaat spelen, want op den duur wil je niet alleen exacte matches maar ook patronen gaan matchen waarbij je in wezen zegt "alles van de vorm X moet naar script Y doorgemapt worden".
Los van het feit dat je al deze regels in een .htaccess bestand moet stampen en je hele applicatie breekt (500 internal server errors) op het moment dat je ergens een fout maakt creëert dit een ander probleem: elke script vormt op dat moment een "voordeur" in jouw applicatie, dus eigenlijk worden al jouw PHP-bestanden afzonderlijke applicaties. Uit oogpunt van security is dat niet erg handig, want elk PHP-bestand zou dan uitgerust moeten worden met eenzelfde soort beveiliging wat op den duur bewerkelijk kan worden als je al deze bestanden up-to-date wilt houden. En als je hier niet heel erg consequent in bent is zo'n voordeur al snel een achterdeur :p.
Het zou dus veel beter zijn om een single point of entry (één enkel stuk code die het toegangspunt tot jouw applicatie vormt) in je applicatie te hebben. Dit heeft ten minste twee grote voordelen:
1. in eerste instantie kan je hele applicatie op één plek opgezet/geinitialiseerd/gebruiksklaar worden gemaakt. Dingen zoals security, database- en sessie-gebruik, het aanmaken van andere hulpobjecten etc. - volgens mij wordt dit ook wel het "bootstrappen" van de applicatie genoemd.
2. Dit punt (wat vaak neerkomt op index.php) kan vervolgens (als laatste stap na initialisatie) ook gebruikt worden om externe aanroepen te vertalen naar interne applicatie-calls. Hiermee heb je dus effectief de "routing" uit het eerdergenoemde externe bestand (.htaccess) binnen je applicatie getrokken en kun je hier de vertaling handmatig uitvoeren. Je hebt hier dan binnen je applicatie volledige controle over. De mapping kan vele vormen aannemen: van een simpel switch-statement naar het opvragen van een item uit een boomstructuur in je database tot het delegeren naar een andere controller voor het verder afhandelen van een request, er zijn legio mogelijkheden.
Het enige wat je dus (vervolgens) in wezen hoeft te regelen is het (intern) doorsturen van alle requests naar je single-point-of-entry. Vervolgens inspecteer je op deze plek het oorspronkelijke request ($_SERVER['REQUEST_URI']) en schrijf je code die de mapping verder afhandelt (of delegeert naar een ander stuk code die dit kan).
Zo zou je dus een externe aanroep van /actie kunnen laten resulteren naar het intern uitvoeren van /custom/actie.php.
Maar dan begint het eigenlijk pas :).
Om te voorkomen dat er conflicten ontstaan tussen de "virtuele" URL's en "fysieke" bestanden of directories met eenzelfde naam is het eigenlijk zaak dat je alle code verplaatst naar buiten je webdirectory om dit soort "botsingen" te voorkomen. Eigenlijk zou je publieke webdirectory dus enkel index.php moeten bevatten, en wat er verder publiek toegankelijk zou moeten zijn zoals CSS, afbeeldingen enzo.
En dan zou je ook eens na kunnen gaan denken over de verdere pagina-opbouw. Idealiter is /actie concreet niet een compleet HTML-bestand in de vorm van /custom/actie.php ofzo. Jouw website heeft vaak een vaste layout (het "maintemplate") en een variabel deel. Dat variabele deel heeft vaak een specifiek doel: een overzichtslijst, een zoekformulier of een artikel. Dit zou je dus als pagina-type kunnen programmeren. Uiteindelijk zou /actie dus kunnen verwijzen naar een of ander database-artikel dat weergegeven wordt door het artikel-pagina-type, misschien geconfigureerd met een wat gepimpt maintemplate om de actie er wat meer uit te laten springen.
Hierbij is er dus voor alle delen die hergebruikt worden aparte code geschreven zodat je je op den duur meer kunt gaan richten op de inhoud van je website, in plaats van dat je telkens het wiel opnieuw aan het uitvinden/uitdraaien bent.
Ondertussen begint de applicatie er steeds meer uit te zien als een soort van content management systeem (CMS).
Gewijzigd op 22/11/2018 18:10:45 door Thomas van den Heuvel
Code (php)
1
2
3
4
2
3
4
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
Alles wordt dus naar de index.php geschreven, tenzij het directories (-d) zijn of bestaande bestandsnamen (-f).
Op de index.php kan je met parse_url de URL uitsplitsen tot in een array.
Thomas heeft er ooit een artikeltje/snippet over geschreven:
Gewijzigd op 22/11/2018 19:55:27 door - Ariën -
dank voor jullie reactie. Het werkt, maar wat mij opvalt, is dat het absoluut niet uitmaakt welk woord je gebruikt om naar de index.php file omgeleid te worden. In mijn geval, laat ik bezoekers www.domein.nl/actie in de browser invoeren, maar dat had net zo goed 'pekingeend' kunnen zijn i.p.v. 'actie'. Je komt altijd op de index.php pagina. Klopt dat?
gr. Timo
In je index.php moet je dit zelf regelen. Ikzelf heb ooit voor een CMS een simpele procedure geschreven die kijkt of een bestand als .php extentie in een bepaalde map bestaat, plus een white-list in een array.
Als er een niet bestaande waarde wordt opgeroepen, geef ik een foutmelding met 404 Not Found header..
Gewijzigd op 23/11/2018 14:52:30 door - Ariën -
Elke webapplicatie zou (en heeft meestal ook) een 404 Page Not Found pagina moeten hebben. Zo kun je bezoek terugsturen naar de bewoonde wereld. Sommige sitebouwers geven hier ook nog een creatieve draai aan.
Het eindresultaat van de "berekening van de pagina" (het omzetten van de externe URL naar de interne URL) levert dus tevens altijd het resultaat "gevonden" (de aanroep was een geldige aanroep en de bijbehorende pagina werd gevonden) of "niet gevonden" (de aanroep was niet geldig) op.
Stel dat jouw website ook afgeschermde delen heeft waarvoor je een login nodig hebt, en je navigeert hier naartoe zonder dat je je hebt aangemeld zou je ook net kunnen doen of deze pagina niet bestaat. Ik heb eigenlijk niet echt goede argumenten voor of tegen deze aanpak gehoord maar uit oogpunt van security lijkt mij dit niet verkeerd, je geeft immers niet met veel toeters en bellen aan dat je onvoldoende rechten hebt om die pagina te mogen bekijken, je doet simpelweg alsof deze niet bestaat en geeft daarmee dus geen ruchtbaarheid aan het bestaan van een beveilighde pagina.
Het lijkt mij altijd het beste om expliciet te zijn in het gedrag van een webpagina, ook al is iets mogelijk soms al default gedrag.
Zo zou ik een "gevonden" HTML pagina altijd voorzien van een 200 OK status code header. En je zult dus de pagina's die volgens jou niet bestaan altijd moeten flaggen als 404 Not Found. Dit doe je met de header() functie. Deze moet aan de webpagina worden meegegeven nog voordat er data van die pagina is verstuurd. Hier komt dus wederom naar voren/boven dat je bij het in elkaar schroeven van een dynamisch gegenereerde pagina na moet gaan denken over hoe je dat structureel aanpakt, dus ook hoe je deze (op protocol niveau) opzet en verstuurt.