Door
Ozzie PHP
op 30-12-2010 16:10
gewijzigd op 06-01-2011 13:17
50.693 views
Hmmm, laat ik de vraag toch maar eens stellen. Ik wil graag een eigen framework / beheersysteem maken. De bedoeling is dat ik als het systeem klaar is heel makkelijk een website kan maken waar meteen al een standaard cms gedeelte in zit.
Ik ben al begonnen met een framework en ik maak daarbij gebruik van Zend Framework, maar nu vraag ik me het volgende af. Ik heb behoorlijk wat PHP kennis en ervaring inmiddels, maar ik heb hier geen opleiding voor gehad. Ik wil het mezelf dan ook altijd zo makkelijk mogelijk maken als ik aan het programmeren ben. Voorbeeld, als ik een databasequery wil uitvoeren dan wil ik niet een hele query in te hoeven typen, maar wil ik simpele functies kunnen gebruiken, bijvoorbeeld: $database->setTable('tabel') en $row = $database->select('naam') etc.
Ook vind ik het handig dat ik in Zend Framework een route makkelijk kan koppelen aan een controller en een actie. Daarnaast gebruik ik de MVC structuur (modules), de Zend_Registry functie om iets op te slaan en gebruik ik de caching functie voor het cachen van gegevens.
Ik gebruik Zend Framework dus voornamelijk voor:
- maken van mooie routes
- routes koppelen aan controller en actie
- MVC structuur (modules)
- Zend_Registry om variabelen op te slaan
- Caching
Voor de rest gebruik in Zend Framework eigenlijk niet. Ik weet dat er heeeel veel mogelijkheden in Zend Framework zitten, maar ik ben niet iemand die dat allemaal wil uitvogelen, en ik wil toch altijd graag mijn eigen code schrijven zodat ik precies weet wat de code doet en hoe deze in elkaar zit (zodat het voor mijzelf logisch is en makkelijk te gebruiken).
Nu vraag ik me 2 dingen af:
1) is het voor mij eigenlijk wel zinvol om Zend Framework te gebruiken aagezien ik er niet heel veel mogelijkheden van benut.
2) zijn de 5 functies waar ik gebruik van maak (makkelijk) ook zelf te maken of is dat heel erg ingewikkeld?
Wat raden jullie aan? Zend Framework blijven gebruiken ook al gebruik ik er maar weinig van? Of toch zelf mijn eigen functies maken en Zend Framework niet meer gebruiken? Ik stel deze vraag ook omdat Zend Framework zo'n 23mb aan serverruimte in beslag neemt.
Hoe is het principe van autoloading... Klopt de nu volgende gedachtengang of zit ik er helemaal naast?
Zodra je een class nodig hebt dan moet die "geladen" worden en volgens mij gebeurt dit via de magische __autoload functie. Klopt dat?
Dus stel je zegt $bla = new Bla() dan wordt de autoload functie getriggered en die vertaalt Bla naar library/Bla.php. Is dat de juiste gedachtengang?
Ik zou me nog kunnen voorstellen dat je een prefix aanbrengt om aan te geven dat het een bepaald type bestand is. Voorbeeld: $bla = new ModelBla(). Nu vertaalt de autooad functie ModelBla naar model/bla.php
Klopt dit nog allemaal wat ik zeg? Zo ja... waarvoor heb je dan include paden nodig, als je via de autload functie alles al regelt? Of klopt mijn bovengenoemde gedachtengang niet?
p.s. ipv $bla = new Bla() kun je ook zeggen $bla = new Bla. De laatste variant is zonder haakjes. Is het aan te raden om alleen haakjes te gebruiken als je variabelen meestuurt?
__autoload() gaat af wanneer je een object probeert aan te maken van een nog niet bekend type (dwz de bijbehorende definitie is nog niet met require() of include() langsgekomen).
de include-paden helpen daarbij: je hoeft dan niet het volledige pad naar je klassedefinitie uit te spellen in __autoload().
Dus je zegt $bla = new Bla(). Autoload zegt include bla.php, en het bestand bla.php wordt gevonden omdat je de include paden hebt ingesteld. Correct?
Maar nu zou ik me kunnen voorstellen dat je je library pad en je model pad niet als include pad instelt, maar de volleidge url in je autoload functie stopt. Dus: include pad/naar/models/bla.php. Dan zeg je dus heel gericht tegen de php parser waar een bestand zich zou moeten bevinden. Is dat vanuit performance oogpunt niet beter? (werkt dit eigenlijk wel voor statiche functie aanroepen of gaat het dan sowieso mis).
p.s. ipv $bla = new Bla() kun je ook zeggen $bla = new Bla. De laatste variant is zonder haakjes. Is het aan te raden om alleen haakjes te gebruiken als je variabelen meestuurt?
Performance kun je beter meten dan gokken. Wanneer je een volledig pad (niet url alsjeblieft) naar je bestand opneemt, vries je je applicatie vast op een bepaalde (machine met) mapindeling.
__autoload() moet je wel *zelf* schrijven! Doe je daar alleen maar include bla.php, dan fikt het alsnog af wanneer het bestand niet bestaat, dat is het risico van het vak. Expliciete paden meegeven betekent ook dat je de indeling van je bibliotheken herhaalt in __autoload(). Een afrader.
Statische functies binnen een klasse maken ook van de klassedefinitie gebruik, en zorgen ook voor autoloading als de betreffende klasse nog niet aan boord is.
Ik zie dat je de haakjes mag weglaten. Waarom zou je dat doen? Ik schrijf ze altijd wel, naar analogie van het aanroepen van een functie.
"Performance kun je beter meten dan gokken. Wanneer je een volledig pad (niet url alsjeblieft) naar je bestand opneemt, vries je je applicatie vast op een bepaalde (machine met) mapindeling."
Wat bedoel je hier mee? Ik snap dit niet helemaal.
"__autoload() moet je wel *zelf* schrijven! Doe je daar alleen maar include bla.php, dan fikt het alsnog af wanneer het bestand niet bestaat, dat is het risico van het vak. Expliciete paden meegeven betekent ook dat je de indeling van je bibliotheken herhaalt in __autoload(). Een afrader."
Ik snap dat je inderdaad een controle moet inbouwen, maar stel de je classes altijd in de map library staan en de models in de map models... waarom zou je dan niet de paden gebruiken? Dan heb je 2 minder include paden toch? Dat betekent minder zoekwerk voor de PHP parser dus een snellere afhandelnig van je request. Of slaat dit totaal nergens op wat ik nu zeg?
"Statische functies binnen een klasse maken ook van de klassedefinitie gebruik, en zorgen ook voor autoloading als de betreffende klasse nog niet aan boord is."
Ah oke, duidelijk :)
"Ik zie dat je de haakjes mag weglaten. Waarom zou je dat doen? Ik schrijf ze altijd wel, naar analogie van het aanroepen van een functie."
Ik schrijf ze ook altijd, maar kwam er een tijdje geleden toen ik een PHP boek las achter dat ze niet noodzakelijk zijn. Ik dacht eerst dat het een foutje van de auteur was :) Maar het werkt wel gewoon zonder haakjes, dus ik vroeg me af of er meer mensen zijn die de haakjes weglaten indien er geen variabelen zijn.
Als je wilt verbeteren op performance, moet je de situatie meten, je verbetering uitvoeren, nogmaals meten, en dan een beslissing nemen. Zorg ervoor dat je je hele applicatie door een profiler haalt, zodat je ook in verhouding kunt zien hoeveel tijd het includen neemt.
Je moet *niet* een architectuurbeslissing nemen omwille van "de performance", zeker niet als je niet kunt voorspellen hoeveel extra werk het je verderop gaat opleveren, en hoeveel performance dat zal kosten. Performance-tuning doe je beter aan een werkende applicatie, in de vorm van refactoring. (en tijdkritische systemen schrijf je niet in PHP)
__autoload() gaat bij elke niet-gevonden klasse af, of dat nu jouw 'classe' of 'model' is. Je moet dan dus op een of andere manier uitvinden waar je het bestand vandaan kunt includen; en dan is include_path zowel sneller als eleganter.
__autoload() gaat bij elke niet-gevonden klasse af, of dat nu jouw 'classe' of 'model' is. Je moet dan dus op een of andere manier uitvinden waar je het bestand vandaan kunt includen; en dan is include_path zowel sneller als eleganter.
Dit begrijp ik nog niet helemaal. Het 1e stukje snap ik, dat ie af gaat bij iedere niet gevonden class. Maar wat daarna komt snap ik niet helemaal.
Stel $bla = new ModelBla().
Ervan uitgaande dat het model pad geinclude is, zegt autoload nu:
include('bla.php') // alleen de bestandsnaam wordt geinclude.
Klopt dat? Zo ja, dan zou je toch ook het model pad niet als include pad kunnen instellen en er voor zorgen dat autoload dit doet:
include('pad/naar/models/bla.php')
Nu weet PHP direct waar het bestand gevonden kan worden en hoeven niet eerst alle include paden te worden afgespeurd.
Dit is ook wel het meest simpele voorbeeld. Het wordt leuker als je automatisch arrays zonder dat je dan een loopje om z moet bouwen. Want waarom zou je dat zelf doen als een framework dat ook voor je kan doen? En waarom zou je standaard CRUD functionaliteit voor elke tabel willen maken en elke query zelf samenstellen als je dit ook generiek kan houden? Daarnaast in mijn voorbeeld wordt de query uitgevoerd en krijg je netjes een mooi resultaat terug waarbij rekening is gehouden met dat je een select doet. Jij hebt alleen nog een string die je moet uitvoeren en waarvandaan je verder moet werken. (Oke beetje onduidelijk uitgelegd miss.). De trend in programmeren van de komende vijf jaar is abstractie van code. Een extra laag zorgt voor extra abstractie. Je beschrijft het WAT en niet het HOE. Ik heb daar nog een mooie presentatie over gezien op de Microsoft Dev Days maar dat zoek ik later nog eens op.
Bijna enkele tabel is anders, daar kan je alleen door middel van omwegen iets generieks van maken. Bovendien wil je dat niet, omdat het dan niet in een oogopslag duidelijk is hoe je tabel eruit ziet. Dit vraagt om het maken van fouten, handmatig SQL schrijven is hier veel minder gevoelig voor.
Daarnaast leest ActiveRecord je database structuur in, dat kan niet anders. Aangezien je database structuur statisch is, is dit weggegooide performance.
Verder zal ik geen flauwe opmerking maken over de trend voor de komende 5 jaar. Wel vind ik dat alle queries in een laag houden genoeg abstractie. Je kan echter ook overdrijven. Bovendien heb ik begrepen dat het uitvoeren van ingewikkelde queries erg omslachtig is in bijvoorbeeld Doctrine.
The Force op 03/01/2011 00:08:01
Waar zeg ik overigens dat ik deze abstractie goed vind omdat het simpeler zou zijn omdat de developer geen SQL hoeft te leren?
Nergens, was meer een algemene opmerking, daar veel voorstanders dit wel als argument aandragen.
The Force op 03/01/2011 00:08:01
Waar zeg ik dat? Je query wordt echt niet aangepast naar standaard SQL. Active Record maakt gebruik van adapters. Elke DB heeft zijn eigen adapter. In een adapter kunnen leuke trucjes, voordelen en functies verwerkt worden. Een ander voordeel is dat deze adapter goed getest zijn dat deze dezelfde resultaten opleveren. Als jij zelf je queries gaat aanpassen dan moet je dit zelf testen. Weer een geval waar je niet met de HOE bezig wil zijn maar met de WAT. Als programmeur wil je bijv. 10 records inserten. Je gebruikt bijv. MSSQL. Multiple inserts is daar niet mogelijk dus hij doet netjes 10 aparte inserts. Je besluit MySQL te gebruiken of er komt een nieuwe versie van MSSQL die dat wel ondersteunt. Wat doe je? Je verwijst naar 'mysql' in de config en voila: multiple inserts. Je download een nieuwe MSSQL adapter voor de nieuwe versie en voila: multiple inserts.
Je zegt dat je alleen een configuratiebestand hoeft aan te passen als je van database wilt switchen. Dit impliceert voor mij dat je dan geen adapter specifieke functies kan gebruiken. Indien je toch vastzit aan een bepaalde adapter, vervalt het grootste deel van je punt van 02/01/2011 21:17:23.
Ook lijkt het mij onwenselijk dat ActiveRecord voor mij gaat bepalen hoe ik de database beheer. Ik houd ervan om alle touwtjes in handen te hebben, dus wil ik weten hoe mijn database omgaat met transacties, inserts, locks en noem zo maar op. Als ik dit weet kan ik optimaliseren op de manier die ik wil. Niet op de manier die ActiveRecord voor mij bepaalt.
Tenslotte weet ik niet precies hoe het aanmaken van klassen gaat binnen ActiveRecord. Indien dit, net zoals veel andere features, op magische wijze gebeurt, kan je het op de juiste plek controleren van data vergeten.
The Force op 03/01/2011 00:08:01
De geavanceerde zoekpagina waarbij een gebruiker aan kan geven waarop hij wil zoeken? Dat iemand aanvinkt op achternaam te willen zoeken en een achternaam op geeft bijvoorbeeld? Zomaar een voorbeeldje, je kan er vast meer verzinnen.
Voor het maken van een zoekfunctionaliteit raad ik je aan om eens te kijken naar tools die daarvoor bedoeld zijn, zoals Lucene of Sphinx. Veel makkelijker en sneller dan allemaal WHERE clausules in elkaar te knutselen.
Doctrine heeft DQL, wat je in staat stelt (even, denk ik) complexe queries te maken als in SQL en toch een ORM te gebruiken. Die DQL maps naar SQL worden gecached zodat je geen performance erop inlevert. Ook is DQL gelijk voor alle DB-backends. De ideale oplossing, zo lijkt mij...
In doctrine kan je trouwens ook een API gebruiken om een query te vormen.