MVC Routing
Bij routing voor je website stuur je eigenlijk alle requests door naar 1 pagina. Meestal index.php.
Doe je dan dus ook de POST data daarnaartoe sturen? En hoe doe je die dan weer doorgeven aan de juiste controller?
En hoe doe je alle get variabelen verwerken? Doe je dan iets als $_GET[0], $_GET[1] etc?
Ik begrijp niet echt wat het voordeel is van een router. Je moet telkens de juiste controllers/models/vieuws includen, soms (volgens mij) onnodig een header gebruiken om een gebruiker door te sturen naar de juiste locatie.
Daarnaast lijkt me het controleren van GET variabelen moeilijker, alles doe je rewriten naar mooie URL's,
Dus dit: www.site.nl/help.php?action=view&item=10023 wordt dit: www.site.nl/help/view/10023
Aan de tweede url zou je niet meer kunnen zien of view een map is, of (de waarde van) een veriabale.
Niet dat dit voor buitenaf belangrijk is, of dat bezoekers hier iets mee moeten. Maar hierdoor lijkt het me verwarrend. Ook zou ik niet weten wat ik moet doen als een pagina direct wordt aangeroepen, dus niet door de router, maar rechtstreeks (zonder include, en dus zonder code die in de router eventueel erboven zou staan, voor het include statement)
Een error 404 geven is dan eigenlijk liegen, doorsturen naar de router en zo een omweg maken lijkt me ook raar.
Gewijzigd op 06/12/2013 15:49:34 door Mark Hogeveen
Bij MVC moet je bepalen wat er gaat gebeuren met die route, welke controller die gaat gebruiken. Dat doet een router. Die kijkt dus alleen, welke controller moet ik nu aanroepen. Is er geen controller gevonden, dan geeft hij een 404. Dat is geen liegen, er wordt een pagina aangeroepen die niet bestaat. We hebben het nu niet meer over dat simpele index.php font controller bestandje, maar over de pagina die je aanroept.
Als je nu rechtstreeks het adres intypt naar welcome.php, roep je die dus aan zonder door de router te gaan.
Bij sommige systemen zie je in de code dat er een error wordt gegeven als "Direct script acces not allowed"
Dit vind ik lelijk.
De WelcomeController handelt bijv. de url index.php/ af. De PostController::showAction handelt index.php/post/123/hello-world af.
Als je naar /controllers/welcome.php gaat bezoek je geen pagina, je bezoekt een bestand met daarin informatie hoe je de url index.php/ moet afhandelen.
Als je naar /controllers/welcome.php gaat, dan bezoek je als het goed is een php Class en krijg je dus geen output te zien. Vandaar dat dit dus vaak met een "Direct access not allowed" wordt geblokkeerd. Je hebt daar namelijk niks te zoeken.
Ja, dat is dus wat ik bedoel.
Je moet het net even iets anders aanpakken. Als je nou enkel en alleen je index.php in je "public" directory zet, en alle overige pagina's in een "private" directory, dan kan niemand via de browser een pagina aanroepen. In je index.php pagina in de public map zet je dan:
In de index.php in de private map ga je dan gewoon verder zoals je dat normaal ook zou doen, alleen staan nu dus alle bestanden in de private map. Het voordeel is dus dat mensen via de browser niet meer rechtstreeks een pagina kunnen aanroepen zoals jij hierboven aangaf. Daarnaast is het een stuk veiliger... omdat mensen niet meer via de browser rechtstreeks een bestand kunnen aanroepen.
Ik hoop dat je iets aan deze tip hebt.
Is het nog gelukt?
@Ozzie, waarom een require naar een private index.php file?
Local Dev op 08/12/2013 00:19:29:
@Ozzie, waarom een require naar een private index.php file?
http://wordpress.stackexchange.com/questions/58391/is-moving-wp-config-outside-the-web-root-really-beneficial
Ik kan me ook vaag herinneren dat ik ooit over een aanval gelezen hebt die de php handler uitschakelde tot je Apache opnieuw opstarte.
Gewijzigd op 08/12/2013 00:55:19 door Dos Moonen
Wat bedoel je precies met je vraag?
Die index.php in je private map is de bootstrap. Door alle bestanden in een private map te zetten kunnen ze niet rechtstreeks via de browser worden aangeroepen en dit vergroot de veiligheid. Maar ik weet niet of dit een antwoord op jouw vraag is, of dat je iets anders bedoelde?
Zelf plaats ik alleen maar mijn index.php, css, js en images in de public directory.
Voor de rest staat alles in de de root directory, maar ik require / include geen bootstrap file, alleen de autoloader die de applicatie start
Ik zie niet wat er raar aan is hoor? Waarschijnlijk staan de dingen die jij dan in je public index.php hebt staan bij mij in de private index.php. Dat is waars. het enige verschil. Ik heb bewust zo min mogelijk code in mijn public index.php staan. Alles staat dan veilig op een plek waar niemand er van buitenaf bij kan.
Je hebt dan toegang tot de "pagina" (het script) maar dat is toch niet onveilig?
Het enigste dat iemand dan zou kunnen proberen is bepaalde input geven met POST of GET requests, maar als je daar rekening mee houdt kan er niks gebeuren toch?
Het is natuurlijk wel logisch om dit soort scripts af te schermen.
Een voorbeeld (niet echt mvc, maar als voorbeeld)
contact.php (formulier etc.)
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['send'])) {
// require het bestand om het formulier te verwerken
require "ContactController.php";
}
?>
<!-- Form stuurt data naar huidige pagina -->
<form method="post" action="">
Bericht: <textarea name="msg"></textrea>
<input type="submit" name="send" value="Verzend" />
</form>
if($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['send'])) {
// require het bestand om het formulier te verwerken
require "ContactController.php";
}
?>
<!-- Form stuurt data naar huidige pagina -->
<form method="post" action="">
Bericht: <textarea name="msg"></textrea>
<input type="submit" name="send" value="Verzend" />
</form>
Als je nu ContactController rechtstreeks zou aanroepen via de browser, zou je een lege pagina krijgen. ContactController denkt dat er een formulier is verzonden, en wil een niet-verzonden formulier verwerken.
Dat zou dus een fout kunnen veroorzaken.
Gewijzigd op 08/12/2013 11:33:49 door Mark Hogeveen
Het is wel onveilig, mensen kunnen dan met bepaalde tools de content van je script lezen. En dat is nou niet echt geweldig...
Maar goed, je moet het vooral zelf weten. Het was een goed bedoelde tip. Wat je ermee doet laat ik helemaal aan jou over.
Van de reactie van Wouter J schrik ik een beetje. Tools waarmee je de PHP scripts kunt zien? Lekker dan... Ik dacht dat dit vrijwel onmogelijk is, dat je dat alleen kon als je echt toegang had tot het FTP.
En wat Ozzie zegt: ik begrijp dus dat als de PHP server eruit ligt, dan wordt de PHP code dus niet meer geparst (logisch) en dus wordt het als plain tekst/html gestuurd naar de client (ook logisch).
Nu toch nog een vraag, na 4 dagen.
Bij een router heb je dus de map en bestandsnamen in een GET variabele staan.
site.nl/public/page.php?item=1234 rewrite je naar site.nl/page/item/1234
Door dit rewriten raak ik juist door de war. Is het voor mij misschien verstandiger, om eerst helemaal niet te kijken naar het herschrijven van URL's, en gewoon eerst eens met niet-herschreven URL's te werken?
Dan komt dat rewriten wel vanzelf?
Kijk eens naar frameworks als ZF2 en Symfony hoe zij dit afhandelen, ik geloof dat je bij het bestuderen hiervan je vraag wordt beantwoord.
Inderdaad, en als je niet ervoor hebt gezorgd dat directories worden afgeschermd zijn al je bestanden ook nog eens zichtbaar. Daarom wil je bestanden die code bevatten dus niet in je public directory hebben staan.
>> Door dit rewriten raak ik juist door de war. Is het voor mij misschien verstandiger, om eerst helemaal niet te kijken naar het herschrijven van URL's, en gewoon eerst eens met niet-herschreven URL's te werken?
Nee, dat zou ik niet doen. Ik zou juist zorgen dat je het principe snapt, om jezelf achteraf een hoop werk en frustraties te besparen ;)
Hoe het in de details werkt ga ik je nu niet uitleggen, maar het principe is in hele grote lijnen als volgt.
URL: jouwsite.nl/fotoalbum/toon/5
Deze URL wordt opgevangen door jouw index.php in de public map en stuur je door naar de index.php in de private map (ook wel bootstrap genoemd). Uiteindelijk komt deze URL in een router terecht en wordt deze opgesplitst in:
- fotoalbum
- toon
- 5
Deze "route" wordt gematched met een controller (de FotoAlbumController) en een actie (de toonAction), waarbij 5 het nummer is van de foto die moet worden getoond.
Dit is even een heel globale uitleg die wellicht een kwartje doet laten vallen ;)
silex. Die toont op een simpele manier hoe je omgaat met routing, etc. Het biedt vele integratie mogelijkheden met andere libraries en je hebt nog steeds bijna alles in de hand!
Of kijk gewoon eens naar een simpele tool als - Routen met alle mogelijke URL's in een lijst, een soort register van alle pagina's dus.
- De URL's niet opslaan in een lijst, maar gewoon uit de URL zelf de informatie halen.
De eerste manier lijkt me het handigst, volgens mij doet Symfony het ook zo. Het nadeel is wel dat je een configuratie moet maken waar je soms dus heel veel routes moet definiëren.
De tweede manier vind ik minder, in sommige gevallen worden de routes nog steeds bepaald door de bestandsnamen van files. Dus als je een file hebt die contactPage.php heet, dan zou de route eruit zien als /contactPage/ terwijl je dit zou willen: /contact/
Je moet dan de naam van het bestand of controller o.i.d veranderen.
Terwijl routing juist onafhankelijk van bestandsnamen moet zijn.