Routing methoden
De routing methodiek die ik nu gebruik is het volgende:
• de uri bestaat uit: http://domein.com/controller/method/param1/...
• lees de URI uit $_SERVER['REQUEST_URI']
• explode de URI in parts
• construeer het include path mbv de parts
• als de controller bestaat instantieer deze
• als de method bestaat roep deze aan met de parameters als argumenten
• bestaat de controller of method niet: 404.php
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$controllerFile = "public/" . $app . "/controllers/" . $controllerPrefix . "Controller.class.php";
if (file_exists($controllerFile)) {
require_once $controllerFile;
} else {
throw new Exception('Controller file does not exist: ' . $controllerFile);
}
$class = ucfirst($controllerPrefix) . 'Controller';
if (class_exists($class)) {
$controller = new $class();
$controller->initLocale($country, $language);
if (isset($urlParam) && !empty($urlParam)){
$controller->index($controllerPrefix, $action, $urlParam);
} else {
$controller->index($controllerPrefix, $action);
}
} else {
throw new Exception("Controller class does not exist") . '!';
}
?>
$controllerFile = "public/" . $app . "/controllers/" . $controllerPrefix . "Controller.class.php";
if (file_exists($controllerFile)) {
require_once $controllerFile;
} else {
throw new Exception('Controller file does not exist: ' . $controllerFile);
}
$class = ucfirst($controllerPrefix) . 'Controller';
if (class_exists($class)) {
$controller = new $class();
$controller->initLocale($country, $language);
if (isset($urlParam) && !empty($urlParam)){
$controller->index($controllerPrefix, $action, $urlParam);
} else {
$controller->index($controllerPrefix, $action);
}
} else {
throw new Exception("Controller class does not exist") . '!';
}
?>
Ik constateer echter dat alle bekendere frameworks, zoals Symphony, Laravel, Slim, etc een routing systeem gebruiken gebaseerd op, wat ik maar noem, een ‘hardcoded’ manier zoals in Laravel:
Code (php)
1
2
3
4
5
2
3
4
5
<?php
Route::get('/', function(){}
Route::post('foo/bar', function(){}
Route::get('user/{id}', function($id){}
?>
Route::get('/', function(){}
Route::post('foo/bar', function(){}
Route::get('user/{id}', function($id){}
?>
Elk framework heeft natuurlijk zijn eigen coding style voor deze functionaliteit.
Hierdoor moet iedere route gecodeerd worden; heb ik 50 controller (niet abnormaal bij ons) moet ik 50x een get of post (of soms beide) regels coderen en dat elke keer als er een nieuwe controller wordt toegevoerd of verwijderd. Met mijn methode hoef ik dat niet en is dus veel generieker.
Mijn vraag daarom: waarom geven de framework toch voorkeur aan het uitschrijven van de uri? Anders gezegd: wat zijn de voor- en nadelen van beide methoden.
Ward:
Graag voortaan bij code de [code][/code]-tags gebruiken.
Hier kun je meer lezen over de mogelijke opmaakcodes.
Alvast bedankt!
Hier kun je meer lezen over de mogelijke opmaakcodes.
Alvast bedankt!
Gewijzigd op 09/12/2016 16:07:56 door Ward van der Put
file_exists() is i.i.g. een dure operatie. Wanneer je gebruik maakt van een autoloader dan heb je genoeg aan enkel een controle met class_exists().
Daarnaast lijkt mij isset($urlParam) && !empty($urlParam) nogal dubbelop, enkel !empty($urlParam) is genoeg, empty()
Gewijzigd op 09/12/2016 16:18:58 door Thomas van den Heuvel
Rob D op 09/12/2016 16:02:55:
Mijn vraag daarom: waarom geven de framework toch voorkeur aan het uitschrijven van de uri? Anders gezegd: wat zijn de voor- en nadelen van beide methoden.
Om bij het einde te beginnen: dat doen ze om expliciet te maken dat route /a/b/ onder verantwoordelijkheid valt van controller X en geen enkele andere controller. Daarnaast kun je dan ook nog route /c/d/ aan controller X hangen én controller X vervangen door controller Y, zonder de routes te veranderen.
In jouw oplossing kan dat niet en zijn die beslissingen allemaal impliciet én hard-coded. Als je bijvoorbeeld een route wilt wijzigen, moet je de naam van de controller wijzigen en daarmee vervolgens ook nog de bestandsnaam van het bestand waarin die controller is opgeslagen. Dat soort trapsgewijze, in de logica van de code verborgen afhankelijkheden moet je zoveel mogelijk beperken.
framework te verbeteren. Veel code is jaren geleden gemaakt en afgekeken van voorbeelden inclusief de fouten :(. Daarom neig ik naar een bestaand framework waar slimmere mensen dan ik aan gewerkt hebben, maar ik wil de code natuurlijk wel begrijpen.
Al ben ik niet zo weg van al dat soort expliciete mappings ontkoppel je je URLs wel van code.
Rob D op 09/12/2016 16:32:06:
Dank je voor jullie input; ik sta voor de keuze om met een bestaand framework te gaan werken of mijn eigen
framework te verbeteren. Veel code is jaren geleden gemaakt en afgekeken van voorbeelden inclusief de fouten :(. Daarom neig ik naar een bestaand framework waar slimmere mensen dan ik aan gewerkt hebben, maar ik wil de code natuurlijk wel begrijpen.
framework te verbeteren. Veel code is jaren geleden gemaakt en afgekeken van voorbeelden inclusief de fouten :(. Daarom neig ik naar een bestaand framework waar slimmere mensen dan ik aan gewerkt hebben, maar ik wil de code natuurlijk wel begrijpen.
Dat is nou precies het probleem. In plaats van bezig te zijn met het bouwen van een website zonder onder de motorkap te hoeven duiken ben je bezig met het ontwikkelen van een framework. Je kunt als individu niet alles zelf ontwikkelen of een klus komt nooit af.
Mijn inziens is het super belangrijk om voor de juiste tools te kiezen én te zorgen dat je hier snel in thuis raakt. Dat kan met wat video tuts, een boek of een heuse cursus. Dit is een kleine investering maar als je naar de uren kijkt heb je dat er zo uit.
Ik heb jullie misschien op heb verkeerde been gezet door met mijn vraag de indruk te wekken dat ik pas kort kom kijken in het PHP wereldje. Ik werk echter al zo'n 15 jaar met o.a. dit taaltje. Wij onderhouden al zo'n 10 jaar een framework dat wij gebruiken voor onze applicaties.
Ons framework wordt ingezet voor voor grote bedrijven wereldwijd. We praten hier niet over een website, maar over meerdere systemen met meerdere gigabytes aan code, gekoppeld aan een Oracle db met een paar honderd tabellen en een paar honderdduizende records.
Ik heb een aantal jaren geleden gekeken naar de bestaande frameworks, maar die konden toen niet de flexibiliteit leveren die wij nodig hadden en hebben. Natuurlijk blijf ik de ontwikkelingen met belangstelling volgen en ben ik geintesseerd in de methoden en technieken die gebruikt worden. Zeker als deze afwijken van methoden die wij (al jaren met succes) gebruiken.
Mijn punt:
Ja, er sluipen fouten in de code, maar die kan je in frameworks ook tegenkomen
Ja, een framework kan je helpen, maar kan je ook tegenwerken en is niet altijd zaligmakend
Ja, een framework kan je op ideeen brengen en daar kan je van profiteren
En ja, een framework kan zich over de jaren verder ontwikkelen zodat het wel een oplossing word.
Maar zelfbouw of gebruik maken van een bestaand framework zal altijd afhangen van de complexiteit, flexibiliteit en dynamiek die de markt vraagt.
Ik stuur zelf met enkele controllers hele websites aan. De meeste routes maak ik gewoon aan in het CMS en in technische termen wordt er voor het gros van de pagina's gebruik gemaakt van één dynamische route en één controller.
De controllers die er bij komen zijn meestal van de geïnstalleerde extra bundles. Deze bundles bieden een fortuin aan functionaliteit en zijn in enkele minuten te installeren en te configureren, wanneer je er mee bekend bent natuurlijk.
Fouten die in de code voorkomen kunnen verholpen worden. Maar je gaat problemen krijgen als je voor tientallen klanten of websites telkens dezelfde fouten moet gaan oplossen, of oplossingen niet meer compatible blijken te zijn. Dan wordt het al gauw een rommeltje. Modulair werken en versiebeheer worden dan ook heel erg belangrijk. Vraag me inmiddels af hoever jullie daar mee zijn.
Waarom denk je dat, als je niet gebruik maakt van Symphony, Laravel of Yii, dat je dan niet modulair kan werken? Wat heeft een framework te maken met Contiunues Delivery met GIT als onderdeel?
Natuurlijk werken wij met modules, imports van bestaande packages en versie beheer. Maar het hoe en welke
bepalen we nu zelf. Wij werken op onze manier al jaren, met een kleine bezetting, tot tevredenheid van onze
klanten. Wij gebruiken 1 framework voor verschillende klanten, vanuit tientallen landen, van over de hele wereld, met elk hun eigen talen en locale.
Dit kunnen wij alleen doen door zeer efficient onze software in te zetten. Echter zo'n oud systeem ontkomt niet aan de beruchte 'software rot'.
Ik kijk dus dan ook met belangstelling naar vernieuwing, waar een framework als Symphony een mogelijk goede optie is. Echter ben ik bang dat het ons, met de bezetting die we hebben en de continue oplever druk van de klant, jaren zal duren om onze code om te zetten. Dit legt een veel te grote druk op onze capaciteit. Wel wil ik onze software proberen deel voor deel om te buigen naar mainstream methoden zodat een eventuele migratiestap naar een regulier framework realistischer wordt.
Dus in theorie heb je gelijk, maar ik heb te maken met de praktijk en moet dit dus pragmatisch oplossen.
Toevoeging op 12/12/2016 12:11:09:
Nog even ter aanvulling: onze applicatie, met alle business rules, validaties, security issues, bestaat voor een zeer groot deel uit php code, webpaginas vol met javascript, Oracle stored procedures. Geen enkel framework levert mij die volledige functionaliteit, je zal die toch zelf moeten bouwen.
Als ik bijvoorbeeld dit zie, dan denk ik: service locator!
Elke controller moet apart geïnitialiseerd worden met land én taal? Zijn er dan geen controllers die prima werken zonder land en taal als twee God particles voor alles overheersende dependencies? En ook over het apart initialiseren van een controller en de rol van een constructor daarbij zijn in het laatste decennium boekwerken aan blogposts volgeschreven.
Als je dit wilt refactoren, dan zou ik waarschijnlijk niet met de routing beginnen. Begin met de fundamentelere bouwstenen, zoals gestructureerde namespaces voor core en apps en een fatsoenlijke autoloader die daarop aansluit.
Ik denk persoonlijk niet dat een PHP-framework bij zo'n grote live codebasis in combinatie met beperkte mensen en middelen (tijd!) de ideale oplossing is: dan moet je te veel ineens verbouwen.
We gaan dus nu onze software aanpakken, maar dat moet gefaseerd gaan en misschien eindigen we wel met Symphony, of eerder Laravel:)
Waar ik wel moeite mee heb is het idee, dat als je geen regulier framework gebruikt, dat je dan fout/dom bezig bent. Ik heb teveel methologien, dogma's, hypes zien komen en gaan, waaronder vele waarvan ik achteraf blij ben dat ik er in ben meegegaan. Er zijn ook genoeg grote(cms/social) producten op de markt die ook hun software baseren op eigen frameworks (en vaak niet al te mooi gebouwd).
Toch als, zoals in ieder bedrijf, standaardisatie belangrijk is het zinvol om altijd (af)kijken naar wat kant en klaar en beproeft beschikbaar is.
Met wat simpele basisprincipes kom je heel ver, ook zonder PHP-framework. Refactoring begint meestal met het afgaan op de stank van code smell. Gebruik je op twee plaatsen dezelfde drie SLOCs? Dan begint het te ruiken naar te vaak gedragen sokken. Heb je een methode met meer dan drie parameters? Dan doet die te veel en ruik je dat aan de zweetlucht.
Voordat je besluit welk (ander) PHP-framework veel beter is, moet je eigenlijk eerst nagaan hoe slecht je eigen framework nu is. Ik kan je het boek Refactoring van Martin Fowler aanbevelen.
Ik zeg niet dat je zonder framework niet modulair of niet met versiebeheer kunt werken. Ik vroeg me enkel af of jullie dat wel deden. Hoop niet dat je me het kwalijk neemt dat ik geen enkel idee heb hoe jullie organisatie werkt :-)
Als je kunt antwoorden met Ja we hebben versiebeheer, migratie en verschillende onderdelen (blokken/bundles whatever) goed op de rails dan zal ik de laatste zijn die zegt dat je nu alle bestaande code moet gaan herschrijven om deze geschikt te maken voor welk framework dan ook.
En natuurlijk een eigen framework/systeem kan ook goed werken maar ik blijf wel van mening dat je tijd en dus geld moet investeren in het ontwikkelen maar ook in het onderhouden van een dergelijk systeem. Zo zijn er met de komst van PHP7 weer een aantal functies komen te vervallen. Maakte je daar gebruik van dan zul je dat vroeg of laat (ik denk vroeg) moeten wijzigen.
>> Nog even ter aanvulling: onze applicatie, met alle business rules, validaties, security issues, bestaat voor een zeer groot deel uit php code, webpaginas vol met javascript, Oracle stored procedures. Geen enkel framework levert mij die volledige functionaliteit, je zal die toch zelf moeten bouwen.
Dat klopt. Maar er zijn wel frameworks die je een goede structuur aanbieden waar je al deze onderdelen in kunt onderbrengen en nog eens kunt hergebruiken ook.
Cheers
Maak/doe eens een uitstapje/onderzoek en/of draai een project met een ander framework. Wie weet steek je er iets van op.
Gewijzigd op 13/12/2016 14:32:57 door Thomas van den Heuvel
- rapid development
- code reuse
- template engine (html/php)
- handige ingebouwde functies zoals:
- snel databases en tabellen aanmaken
- queries schrijven
- onderlinge relaties met tabellen.
- onderscheidt tussen dev en live
- meestal een handige debugger
- etc...
Zo kan ik het lijstje nog wel even blijven aanvullen :)
Maar ik snap dat het lastig qua tijd en groei om alles te moeten overzetten naar een framework.
Ik begrijp en ondersteun je punt over het gebruik van framework. Wat ik duidelijk wil maken is dat we wel een framework hebben. Een framework dat ik samen met een collega ruim 10 jaar geleden heb gebouwd.
Dat is wat ik ook aangaf in de 1e regel van mijn oorspronkelijke vraag.
Dit 'framework' is een MVC gebaseerd systeem, met routing, security modules, database abstractie (adodb), een mailer syteem. Geen template systeem voor de views, maar een page/form generatie systeem gebaseerd op phphtmllib, etc., etc.
Misschien is het in het verhaal belangrijk te weten dat we jaren geleden uit een volledige Oracle omgeving kwamen en onze programmeurs evenveel weten als de doorsnee DBA. Databases en queries maken zijn onze dagelijks brood. Wij maken geen websites, maar een complex transactie systeem, met honderden views en tabellen.
Dit systeem is echter verouderd en uit zijn voegen gegroeid maar in principe kan het alles en voldoet nog ruim aan de eisen van de markt. Ik heb reeds een nieuw framework gebouwd, maar eenvoudiger, meer op moderne principes, om onze apps 'leaner and meaner' te maken. Daarom kijk ik nu naar wat er in de php wereld is vernieuwd.
Mijn keus is dus: wat ga ik doen, ons nieuwere framework complient maken met de laatste stand van zaken in de php wereld (wat mijn programmeurs hart wil) of het adapteren van een bestaand framework dat zich reeds heeft bewezen in de markt (wat mijn managers hart wil).
Ons eigen framework voldoet en heeft zich bewezen; wij weten hoe we een framework moeten maken; zodra de basis er staat wordt die over de jaren nauwelijks nog gewijzigd. De functionele software (forms, javascript, db tables, business rules, proces flow, calculaties, gegenereerde pdf's en excel docs, (rest/soap) interfacing, etc) wordt bij ons wel dagelijks voor de ene of andere klant onder handen genomen. Dat levert een framework niet, maar is de eigenlijk core van elk systeem.
Vandaar dat ik mij niet zo druk maak over wat een framework voor ons mogelijk sneller kan doen; daar zit onze tijd niet in.
Waar het mij om gaat is om onze manier van bouwen mee te laten groeien met wat de markt doet. Als er iets beters, makkelijk of sneller is wil ik dat adapteren (ook als dat een nieuw framework betekent). Ik merk zowiezo al dat ik weer nieuwe dingen kan leren en ben daarom ook zeer blij met jullie input.
Toevoeging op 13/12/2016 22:32:28:
Thomas, ik zat te denken om een klein project te beginnen met Slim en die aan te vullen met de modules die ik nodig heb. Zo leer ik de pro's en cons stap voor stap. Maar misschien is het beter om meteen te beginnen aan een framework zoals Laravel of Symphony ...
Toevoeging op 14/12/2016 09:53:40:
Thomas, om even terug te komen op je opmerking over de empty() functie. Volgens mij test deze functie niet of de variabele bestaat.
Als bijv. $tstVar niet bestaat zal empty($tstVar) == true geven, terwijl isset($tstVar) == false geeft.
empty() geeft in dat geval geen melding, waar isset() dat wel doet.
Dank julle beide.
Rob D op 13/12/2016 22:07:32:
Mijn keus is dus: wat ga ik doen, ons nieuwere framework complient maken met de laatste stand van zaken in de php wereld (wat mijn programmeurs hart wil) of het adapteren van een bestaand framework dat zich reeds heeft bewezen in de markt (wat mijn managers hart wil).
Een programmeur: wil een gedegen, flexibel en stabiel systeem
Een manager: wil zo snel mogelijk een werkende oplossing
Kiezen voor een bestaand systeem is leuk, maar de leercurve van zo'n systeem is bijzonder groot. Weet je eindelijk na een jaar hoe alles een beetje werkt, komt er een nieuwe versie en werkt alles ineens anders. Of ... na 2 jaar besluiten de makers ineens om het systeem niet verder door te ontwikkelen. En dan?
Als ik jou zo hoor dan gaat het bij jullie om je core business. Ik zou me daarbij nooit afhankelijk maken van een extern framework. Wat zeg je straks als er iets niet werkt (vanwege een lek)? Geef je dan dat externe framework de schuld? In jouw geval zou ik dus altijd ervoor kiezen om je eigen framework te maken. Op de lange termijn is dat de veiligere oplossing.
Als ik naar bijv. het routing systeem kijk van Slim of Laravel dan zijn die superflexibel, maar die flexibiliteit kan ook leiden naar onduidelijkheid. De ontwikkelaars willen een strakke, heldere methodiek, dat altijd werkt als je je maar aan de regels houdt.
De keuze is enerzijds lastig omdat ik niet voor Laravel wil kiezen en er dan achter komen dat ik eigenlijk Symphony nodig had. We hebben geen tijd om al die frameworks uit te proberen.
En van de andere kant heb ik een luxe positie, omdat we een systeem hebben dat werkt. Het huidige systeem is ontstaan door af te kijken en te nemen wat voor ons werkt, waarom zouden we dat dan nu ook niet doen.
Hoe dan ook is het een feit dat in de moderne frameworks veel best practices zitten die waard zijn om te gebruiken. Ook moet je rekening houden met het feit dat huidige frameworks veel modules bevatten die gemakkelijk zijn over te nemen of waar alternatieven voor bestaan.
Kortom, ik hoop door middel van een paar kleinere projectjes met verschillende frameworks een gevoel te krijgen welke kant we op gaan.