eigen framework / beheersysteem
Pagina: « vorige 1 2 3 4 5 6 7 ... 10 11 12 volgende »
Ozzie PHP op 03/01/2011 15:14:16:
Graag deze discussie stopzetten heren. Ik wil graag m'n topic weer terug! ;)Kunnen we dit database verhaal alsjeblieft stopzetten nu? Standpunten van jullie beiden zijn inmiddels duidelijk ;)
Ozzie PHP op 03/01/2011 14:27:28:
Thanks voor je toelichting.
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.
Of zie ik het nu verkeerd?
Bas Cost Budde op 03/01/2011 13:57:37:
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. __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.
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.
Of zie ik het nu verkeerd?
Vaak is het handig om niet __autoload te gebruiken, maar spl_autoload_register() waarmee je een autoload klasse registreert. Hier kan je dan bijvoorbeeld een prefix (Zend_) en een map meegeven. Dit is veel handiger dan handmatig te includen, omdat je dan maar 1 string hoeft aan te passen wanneer je de lib verplaatst.
pffff... nu raak ik helemaal de weg kwijt. Weet je hier toevallig ergens een voorbeeld van te staan? Of kun je wellicht zelf een stukje code tonen zodat ik begrijp wat je bedoelt?
Quote:
@Niels,
Kijk eens naar een abstracte methode:
Kijk eens naar een abstracte methode:
Ik heb gekozen voor een interface omdat je er op gewezen wordt als je de methode load niet hebt geprogrammeerd. (Moet je wel de interface implementeren dat wel:)) En voor later is het handig voor als je bepaalde functies verplicht wilt maken. En uiteraard had je die eerst moeten bedenken maar goed je weet natuurlijk nooit op wat voor ideeën je later nog eens opkomt. Maar is misschien ook wat persoonlijke keuze.
Quote:
Het aangekondigde Symfony Reloaded lijkt veelbelovend, vooral de ideeën achter de Kernel en Dependency Injection zijn indrukwekkend
Zeker zeker zeker:) En laat ik nu net op verzoek van ozzie en jasper een tutorial over Dependency Injection aan het schrijven zijn..
Quote:
wat is overigens dat "lazy registreren van een object" waar Niels het eerder over had?
Precies, zoals pim en the force zeggen. Hier op PHPhulp is wel eens zo'n registry klasse in de script library toegevoegd: klik. Het wordt overigens overal voor gebruikt. Google eens op die term dan zal je genoeg informatie tegenkomen.
Quote:
Een leuke tutorialreeks daarover
Dat bedoelde ik niet echt maar goed ;)
Quote:
Of kun je wellicht zelf een stukje code tonen zodat ik begrijp wat je bedoelt?
Die heb ik je toch gegeven een paar berichten terug? Of is dat niet wat je bedoeld?
Offtopic:
leuk topic dit :)
Gewijzigd op 03/01/2011 19:00:50 door Niels K
Niels Kieviet op 03/01/2011 18:59:01:
Hehe... inderdaad :)Offtopic:
leuk topic dit :)
leuk topic dit :)
Met die code bedoel ik dat spl_register_autoload ding....
Zo'n lazy object is wel mooi :) Maar wat is nu bijvoorbeeld het verschil of je een instantie van een object via een class ophaalt of via de class zelf? Waarom dus Registry::get('Database') en niet gewoon Database::get() ?
Anyhow... om maar weer eens helemaal naar het begin terug te gaan... Mijn vraag was dus of ik een eigen framework / cms systeem zou gaan bouwen... en het antwoord is... JA! Ik ga het gewoon doen :)
Wat ik nou in ieder geval heel handig zou vinden is om een soort genummerd lijstje te maken met wat er allemaal in moet. En dan ook met links er bij die ik kan gebruiken om dat specifiele onderdeel te bouwen. De bedoeling is dan dat ik uiteindelijk voldoende input heb om een frameworkje te bouwen. Het hoeft niet superingewikkeld te zijn, uiteindelijk is het de bedoeling dat ik een mooi systeempje heb waarmee ik makkelijk uit de voeten kan.
Wat ik tot nu gezien heb en wat ik zelf als heel handig ervaar zijn de onderstaande punten. Maar ik hoop dat jullie het lijstje dus aanvullen met handige (niet al te ingewikkelde)programmeertrucs die niet in mijn framework mogen ontbreken eventueel voorzien van links naar tutorials.
Tot nu toe:
1) MVC framework link
2) Router vervangen door betere versielink
3) Database active record link
4) method chaining $this->db->select('title')->from('mytable')->where('id', $id)->limit(10, 20);
5) Lazy registreren objecten link
Wat moet er nog bij?
Quote:
Met die code bedoel ik dat spl_register_autoload ding....
Wat snap je niet van deze uitleg?
Quote:
Zo'n lazy object is wel mooi :) Maar wat is nu bijvoorbeeld het verschil of je een instantie van een object via een class ophaalt of via de class zelf? Waarom dus Registry::get('Database') en niet gewoon Database::get() ?
Ik snap je niet helemaal. maar je wilt dus elke keer new Database doen? Of van alles een singleton maken? Ik snap ik je nu verkeerd?
Het principe van een registry is dat je objecten registreert en ze overal weer kunt opvragen.
Gewijzigd op 03/01/2011 20:47:55 door Niels K
Niels Kieviet op 03/01/2011 20:47:18:
Wat snap je niet van deze uitleg?
Ik snap je niet helemaal. maar je wilt dus elke keer new Database doen? Of van alles een singleton maken? Ik snap ik je nu verkeerd?
Het principe van een registry is dat je objecten registreert en ze overal weer kunt opvragen.
Quote:
Met die code bedoel ik dat spl_register_autoload ding....
Wat snap je niet van deze uitleg?
Quote:
Zo'n lazy object is wel mooi :) Maar wat is nu bijvoorbeeld het verschil of je een instantie van een object via een class ophaalt of via de class zelf? Waarom dus Registry::get('Database') en niet gewoon Database::get() ?
Ik snap je niet helemaal. maar je wilt dus elke keer new Database doen? Of van alles een singleton maken? Ik snap ik je nu verkeerd?
Het principe van een registry is dat je objecten registreert en ze overal weer kunt opvragen.
Ik snap het hele autoload principe nog niet goed... wel dat magische __autoload, maar ik begrijp niet wat spl_register_autoload precies doet en wanneer je dat moet gebruiken.
Zoals ik al eerder meldde heb ik geen IT opleiding gehad en ben dus niet zo heel bekend met design patterns, maar die Database is dan volgens mij een singleton. Met get roep ik dan telkens dezelfde instantie van de database aan. Dus daarom mijn vraag waarom je dan een registry gebruikt. Wat is precies het verschil?
Quote:
Ik snap het hele autoload principe nog niet goed... wel dat magische __autoload, maar ik begrijp niet wat spl_register_autoload precies doet en wanneer je dat moet gebruiken.
In het kort, moet je een auto loader registreren. Dit houd in dat als er een klasse / interface wordt aangeroepen dan kijkt de autoloader of die gevonden wordt. zo niet dan wordt een methode die je hebt opgegeven als parameter aangeroepen met de klasse/interface als parameter en kun je het corresponderende bestand importeren.
Het gebruik is als volgt:
Snap je?
Quote:
Zoals ik al eerder meldde heb ik geen IT opleiding gehad en ben dus niet zo heel bekend met design patterns.
Die heb ik ook niet gehad in mijn opleiding. Verder dan or die + hoe werk ik SQL injections in de hand ben ik ook niet gekomen. Totdat ik hier op phphulp kwam en werd afgekraakt tot Jericho. Daarna was het gewoon veel vragen stellen en veel googlen en lezen lezen lezen.
Quote:
maar die Database is dan volgens mij een singleton.
Die van dat MVC framework? Ja dat klopt. Maar dat is nergens voor nodig. Daar zijn singletons helemaal niet voor bedoeld.
Singleton is bedacht voor het oplossen van een ander probleem: klik op te lossen: klik en die zul je in PHP bijna nooit tegenkomen.
Quote:
Met get roep ik dan telkens dezelfde instantie van de database aan. Dus daarom mijn vraag waarom je dan een registry gebruikt. Wat is precies het verschil?
- Je houdt alles op 1 plaats
- Je kan er altijd bij
- enz
Ik bedoel dan heb je bijvoorbeeld in je script het volgende:
Framework_Config::get();
Framework_Database::get();
Framework_Config_Ini::get();
Framework_View::get();
Dat kan je beter op 1 plaats beheerbaar houden. Als jij bijvoorbeeld de methode get toch wilt veranderen naar getDatabase() dan moet je eerst heel je applicatie doorlopen en alles gaan veranderen.
Gewijzigd op 03/01/2011 21:15:51 door Niels K
Begrijp ik nu goed dat je spl_autoload_register(array('AutoLoader', 'loader'));
gebruikt in plaats van de __autoload functie?
Framework_Database::get();
Dit geeft een instantie terug van de database? En altijd dezelfde instantie? Wat is dan het verschil met Regisrty::get('Database'), of komt dat op hetzelfde neer?
Ozzie PHP op 03/01/2011 21:27:44:
Framework_Database::get();
Dit geeft een instantie terug van de database? En altijd dezelfde instantie? Wat is dan het verschil met Regisrty::get('Database'), of komt dat op hetzelfde neer?
Dit geeft een instantie terug van de database? En altijd dezelfde instantie? Wat is dan het verschil met Regisrty::get('Database'), of komt dat op hetzelfde neer?
Volgens mij wil je hier juist een Registery gebruiken om juist niet aan singletons vast te zitten. Als je overal in je code Framework_Database::get() doet, kan je je database-class niet even gemakkelijk meer vervangen met een andere die dezelfde public interface* heeft. (waarom zou je dat willen? Omdat dat heel gemakkelijk debugt, en het theoretisch mooier is)
Ander probleem met singletons: hoe ga je je database de logingegevens meegeven voor de eerste keer verbinden? Nog een static method? En hoe ga je dan twee database-verbindingen naast elkaar maken? Framework_Database net niet helemaal singleton maken, zodat je en de default instantie hebt, en je nog eigen instanties kan maken? Dat wordt heel rommelig, en het is heel simpel op te lossen met een registery of een andere container.
* public interface van een class is alle publieke methods en hun argumenten. Als die voor twee classen hetzelfde zijn, of deels hetzelfde zijn en alleen die methods die hetzelfde zijn gebruikt, dan kan je die twee classes zonder problemen uitwisselen. Interfaces in PHP zijn een manier om dat af te dwingen (dat twee classes dezelfde public interface hebben, en dat je kan controleren of je een class hebt die inderdaad die interface heeft, via instanceof. Maar dat is allemaal detail.)
In welke gevallen gebruik je een interface als ik vragen mag? Toch niet overal neem ik aan?
Ozzie PHP op 03/01/2011 22:57:34:
In welke gevallen gebruik je een interface als ik vragen mag? Toch niet overal neem ik aan?
Ik doe het zelf eigenlijk alleen als ik een functie/method maak die een bepaald object als argument accepteert, en dan verwacht dat dat object een bepaalde method heeft. Of, en dat komt bij mij in de praktijk vaker voor, die de interface gebruikt om te kijken of het object bepaalde features ondersteunt.
Voorbeeldje: een method die een willekeurig object naar HTML kan omzetten. Maar sommige objecten kunnen dat zelf beter, dus die mogen het dan zelf doen.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
interface HTMLExporter {
public function asHTML();
}
class Color implements HTMLExporter
{
public function asHTML()
{
return sprintf('#%02x%02x%02x', $this->red, $this->green, $this->blue);
}
}
class String implements HTMLExporter
{
public function asHTML()
{
return htmlspecialchars($this->chars, ENT_COMPAT, $this->encoding);
}
}
class Registery
{
// dit ding omzetten naar HTML heeft geen zin, dus niet geïmplementeerd.
}
function printHTML(HTMLExporter $object)
{
echo $object->asHTML();
}
?>
interface HTMLExporter {
public function asHTML();
}
class Color implements HTMLExporter
{
public function asHTML()
{
return sprintf('#%02x%02x%02x', $this->red, $this->green, $this->blue);
}
}
class String implements HTMLExporter
{
public function asHTML()
{
return htmlspecialchars($this->chars, ENT_COMPAT, $this->encoding);
}
}
class Registery
{
// dit ding omzetten naar HTML heeft geen zin, dus niet geïmplementeerd.
}
function printHTML(HTMLExporter $object)
{
echo $object->asHTML();
}
?>
Een instantie van Registery kan je niet aan printHTML geven, Color en String wel. Maar dit voorbeeld is wat te gestript om nuttig te zijn. Je komt het later vast nog wel eens tegen, het is iets waar je je in je begintijd van OOP nog niet druk over hoeft te maken.
Interfaces hebben in PHP sowieso niet veel toegevoegde waarde aangezien ze pas bij runtime worden gecontroleerd (in tegenstelling tot bijv. C++) en je net zo goed van ducktyping* kan uitgaan, aangezien dat ook wel een fout genereert tijdens runtime.
* ducktyping is dat het PHP niet uitmaakt wat voor object het is, zolang het maar werkt. If it walks like a duck and quacks like a duck, it is a duck. In C++ e.d. heb je dat niet omdat je daar nog met allemaal geheugendingen zit, en een hele (heerlijk) strenge compiler.
Al met al heeft nog niemand mn lijstje aangevuld :-(
Andere dingen die handig zijn:
Helaas, geen design patterns of architectures, maar gewoon ouderwetse tips voor programmeren. Want zeker bij een framework zijn die dodelijk essentieel.
- duidelijke variabelenamen. Dingen als $counter zijn niet duidelijk, want wat telt die $counter dan? Je kan hele mooie code schrijven, maar als niemand begrijpt wat er staat gaat niemand het gebruiken, inclusief jijzelf over een jaar.
- begin simpel. KISS. Implementeer pas iets als je merkt dat je het nodig hebt, en wees hier heel strikt in. Aanpassen voor andere doeleinden, features implementeren die je voor een andere site nodig zou kunnen hebben kan altijd nog. Het beste framework heeft niet meer features dan anderen, maar het beste framework lost jou probleem het gemakkelijkst en mooist op.
Voorbeeld... als een class maar 1 keer mag worden aangemaakt, dan kun je singleton toepassen, maar volgens mij kijkt die bij iedere aanroep van de class of de instantie al een keer is aangemaakt. Stel dat je een of andere config class hebt die per pagina aanroep misschien wel 15 keer op verscihllende plekken wordt gebruikt, dan betekent dit dat die controle of die instantie bestaat ook 15 keer wordt uitgevoerd. Niet goed voor je performance lijkt me. Dus wat had ik gedaan... per pagina request wordt de betreffende class 1x geset en kun je de class aanspreken met get(). Als je probeert een nieuwe class aan te maken, dan werd een functie aangeroepen die een exception gooit waarin staat dat je die class alleen met get() kunt verkrijgen. Het werkt prima, maar of dit de juiste manier is...... ???????? Maar het werkt dus wel heel makkelijk, want als je de class nodig hebt gebruik je altijd get, er hoeft geen controle te worden gedaan omdat de instantie altijd geset is. Een nieuwe class aanmaken gaat niet, want dan krijg je een exception.
Maar dit is maar een relatief klein probleem waar je tegenaan gaat lopen, er zijn nog veel grotere zodra je probeert daadwerkelijk iets werkends te maken.
Hoe bedoel je dat je X niet kunt vervangen? Stel je roept in een class de database aan met Database::get() en nu wil je de database class vervangen... dan kun je de huidige database class toch vervangen door een andere? Of bedoel jij iets anders (misschien een code voorbeeldje?)
Stel dat je zo'n dependency injection container gebruikt, dan kan je ergens in een bestandje waar je de container opbouwt zeggen dat Container::get('database') niet een Database object teruggeeft, maar een TestDatabase. Je kan er zelfs een if-else statement omheen bouwen. IF dit-is-mijn-localhost THEN TestDatabase ELSE Database.
Ah oke, op die manier. Ik snap ongeveer wat je bedoelt nu. Maar wel lastig om dat allemaal in elkaar te zetten denk ik :) Ben er wel even zoet mee vrees ik...
Ozzie PHP op 03/01/2011 20:02:29:
Om op je lijstje terug te komen:
2 is geen betere router... (Die in de comments wel ;) )
5 vind ik niet zo sterk, omdat je bij de configuratie van de te lazy-loaden objecten geen methode op kan geven die bij het maken aangeroepen moet worden. Ook heeft het geen mooie interface om te kunnen configureren, omdat je niet mooi data uit dezelfde registry/container kan halen. Kijk toch eens naar Pimple.
Een voorbeeld van wat wel kan met zo'n container, maar niet met de door jou genoemde registry:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
$c = new Container();
// parameters
$c->mailer_class = 'Zend_Mail';
$c->mailer_username = 'fabien';
$c->mailer_password = 'myPass';
// objects / services
$c->mailer_transport = function ($c) {
return new Zend_Mail_Transport_Smtp(
'smtp.gmail.com',
array(
'auth' => 'login',
'username' => $c->mailer_username,
'password' => $c->mailer_password,
'ssl' => 'ssl',
'port' => 465,
)
);
};
$c->mailer = function ($c) {
$obj = new $c->mailer_class();
// Deze configuratie kan niet in een registry
$obj->setDefaultTransport($c->mailer_transport);
return $obj;
};
// get the mailer
$mailer = $c->mailer;
?>
$c = new Container();
// parameters
$c->mailer_class = 'Zend_Mail';
$c->mailer_username = 'fabien';
$c->mailer_password = 'myPass';
// objects / services
$c->mailer_transport = function ($c) {
return new Zend_Mail_Transport_Smtp(
'smtp.gmail.com',
array(
'auth' => 'login',
'username' => $c->mailer_username,
'password' => $c->mailer_password,
'ssl' => 'ssl',
'port' => 465,
)
);
};
$c->mailer = function ($c) {
$obj = new $c->mailer_class();
// Deze configuratie kan niet in een registry
$obj->setDefaultTransport($c->mailer_transport);
return $obj;
};
// get the mailer
$mailer = $c->mailer;
?>
6: UNIT TESTING!