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.

Ik gebruik Zend Framework met name omdat ik mooie routes kan maken, bijvoorbeeld www.mijnsite.nl/kantoorartikelen/nietmachine in plaats van www.mijnsite.nl/?category=4&product=2.

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 je het set en hoe je het get heeft niet zo veel met elkaar te maken.
Zelf vind ik in de view extract() wel mooi, dan kan je gewoon $name gebruiken.
Oh, wist niet dat dat kan... is inderdaad wel erg mooi :)
Echt een heel cool topic :) Ik denk dat veel mensen hier wat aan hebben! In combinatie met deze twee topics is al gauw de basis van OO gelegd:

- topic 1
- topic 2

En verder helpt deze tutorial om de echte beginselen te planten.

Maar goed dat was even offtopic :)


unit testing

En ga fouten maken, daar leer je het meeste van. Al moet je dan niet bang zijn om regelmatig even een stap terug te doen en eerst even de gemaakte fouten te gaan herstellen. Neem dus ook een platform die je op jouw fouten wijst en zorg dat de fouten z.s.m. zichtbaar worden. Test driven development, TDD, is hier ideaal voor, dit is gemaakt om fouten direct aan het licht te brengen.

http://en.wikipedia.org/wiki/Test-driven_development


<?php echo $data->name; ?>

Ik maak gebruik altijd $this->name. Dat vind ik wel netjes.


Ik vind het maar lastig met die container en registries

Eerst een verhaaltje: Bijna 100 jaar geleden (September 1908 om precies te zijn) bracht Henry Ford zijn eerste Ford Model T (ook wel Tin Lizzie genoemd) op de markt. Zoals waarschijnlijk wel bekend, werd de Model T de eerst op zeer grote schaal geproduceerde auto. De vraag naar auto’s steeg tijdens de begindagen van de Model T enorm. Auto’s werden voor meer mensen dan alleen de elite beschikbaar.
Henry Ford had moeite om aan de vraag te voldoen. In de eerste maanden dat de Model T werd produceerd werden er slechts 11 auto’s per maand geproduceerd. Dit alles gebeurde in de fabriek van Ford op ‘Piquette Avenue’ in Detroit. In 1910 waren er ‘slechts’ 12.000 Model T Ford auto’s geproduceerd en dat was het moment dat Henry Ford de productie verplaatste naar het Highland Park Complex, waar tot op de dag van vandaag de archivering plaatsvindt voor Ford.
In het Highland Park Complex werd de assemblagelijn ontwikkeld. Henry Ford deed dit niet zelf, het was één van zijn medewerkers die in een frabriek in Chicage een straat gezien had die kippen deassembleerde. De deassemblage (klinkt mooi, niet waar?) van de kip gebeurde in deze fabriek op een gecontroleerde manier, stapje voor stapje en volledig automatisch. Tegenwoordig worden op de meeste gruwelijke manieren kippen middels uitbeenmachines, ontbeenmachines en nog veel meer machines met gruwelijk namen gedeassembleerd. Met meestelijke efficiëntie worden miljoenen kippen (gok ik) per dag gedeassembleerd. Maar goed, terug in het onderwerp. De persoon die dit allemaal zag dacht: Als we dat nou in de omgekeerde volgorde doen (assemblage in plaats van deassemblage) maar dan voor auto’s. Het was dus niet the boss himself die de assemblagelijn introduceerde, maar goed, hij was wel degene die de gok durfde te nemen deze revolutionaire manier van produceren uit te proberen.
Gauw naar het jaar 1914. Dit was het jaar dat er elke 93 minuten een Model T Ford van de band rolde. Een paar jaar eerder waren dit zoals al verteld slechts 11 per maand geweest. Als je ervan uitgaat dat men 8 uur per dag en 5 dagen per week assembleert betekend dit dat Ford meer dan 10 keer zoveel auto’s kon produceren per maand. De assemblagelijn had dus zijjn succes bewezen! Natuurlijk was niet alleen de assemblagelijn de grote reden dat er elke 93 minuten een Model T Ford van de band rolde. Ook de introductie van de 5 daagse werkweek en het vaste loon, onafhankelijk van de ‘productie’ van de medewerker waren belangrijke factoren die meehielpen bij een snelle producten van de Model T Ford. Die Henry Ford had de zaakjes goed voor mekaar dus.
Even iets dieper inzoomend op de assemblagelijn. Deze lijn klikt verschillende onderdelen aan elkaar, om uiteindelijk een auto te fabriceren. De onderdelen zelf zijn op een ander tijdstip gemaakt en zijn zo gemaakt dat ze op andere onderdelen aansluiten (boutjes, moertjes, schroefjes, pasvormen). Zo zal een kogelvrije vooruit voor een Model T Ford (zouden ze die al hebben gehad?) dezelfde vorm gehad hebben gehad als een vooruit waarmee een gewone man het moest doen. Ditzelfde geldt voor de wielen. Winterbanden (geloof niet dat ze die hadden) zul je op ongeveer dezelfde manier op de Model T Ford gezet hebben als normale banden.
Als eerste kunnen we constateren dat de assemblage van de verschillende componenten waaruit de auto bestaat volledig en voor 100% losgekoppeld is van het daadwerkelijk functioneren van deze componenten. Dit is logisch lijkt mij. Een cake bakt zichzelf niet, daar heb je een recept voor nodig en iemand die de eieren, bloem, suiker en dergelijke door de mixer haalt en in de over zet. Hetzelfde geldt voor een huis, dat bouwt zichzelf ook niet. Je hebt daar architecten voor nodig die een bouwtekening maken, metselaars en timmermannen voor de bouw van het huis. En ook een auto bouwt zichzelf niet, die wordt geassembleerd.
Een interessante vraag is waarom die assemblagelijn nu eigenlijk zo succesvol is. De algemene mening hierover is dat specialisatie efficientie bevorderd. Als je je als persoon ergens in specialiseert wordt je er beter in. Dat kunnen we ook over machines zeggen. Als je een machine bouwt die specifiek moertjes op boutjes draait, zal het gemakkelijker zijn deze machine hierop te specialiseren.
De algemene mening binnen de productiewereld is ook, dat het zich specialiseren in geval van mensen ook nadelen heeft. Overspecialisatie kan leiden tot mensen die hun werk saai gaan vinden, specifieke blessures krijgen door steeds het zelfde werk te doen (RSI, etc).
Maar goed laten we nog even bij de assemblagelijn blijven. Het onderliggende princiepe van de assemblagelijn is dus specialisatie. Dus met andere woorden; het zich richten op één deelprobleem tegelijkertijd zorgt voor een efficienter en gemakkelijker manier van het oplossen van een groter probleem. Door verschillende delen van de assemblagelijn zo in te richten dat ze elk één klein deel problemen oplossen (het op de auto schroeven van de banden, het plaatsen van het motorblok, etc) en de assemblage in zijn geheel los te koppelen van de eigenlijke functies van de auto, wordt het mogelijk om:
- Elk individuele stap in de assemblage te optimaliseren
- Elke individuele stap in de assemblage te beschrijven en herhaalbaar te maken zodat bij het inrichten van een nieuwe assemblagelijn er slechts een copy-paste actie uitgevoerd hoeft te worden.
- De individuele stap te observeren ten einde kwaliteitstestjes in te voeren die specifiek gericht zijn om deze stap in het proces te controleren (is de schroef wel goed vastgedraaid, enzovoort).
- Ten einde het hele proces van het in elkaar zetten van de auto (bijna) oneindig veel te optimaliseren en controleren.


Mmm.. Leuk dit allemaal maar ik geloof dat we op een php forum zitten? Juist ja, maar als je het bovenstaande stuk nog eens leest in het licht van php, dan moeten er toch wel lichtjes gaan branden nietwaar? Maar goed nog even terug naar de auto: die bestaat uit een (zeer grote) verzameling onderdelen die allemaal een belangrijke rol spelen in het laten rijden van de auto. De auto dient geassembleerd te worden. We zouden middels object-orientatie ook de auto kunnen modelleren:
- Car
- Engine
- Wiel
Maar als we dat doen, dan moeten we nog wel iemand hebben die voor ons die auto (de applicatie) assembleert. Dat is waar Dependency Injection, afgekort DI, om de hoek komt kijken.
Echter Dependecy Injection lost het probleem van de assemblage van een applicatie op, niet het gedrag van de componenten die zijn geassembleerd, of de communicatie tussen deze componenten. Separation of Concerns (problemen opdelen in sub-problemen) is een goed principe en ik zou bijna zo arrogant willen zijn door te zeggen dat niemand meer een applicatie moet willen bouwen zonder zich op één deelprobleem tegelijkertijd zou moeten focusen en de individuele componentjes die deze deelproblemen oplossen te assembleren doormiddel van Dependency Injection.
Hoe je die assemblage precies vormgeeft is natuurlijk vraag twee. Maar daar heb je volgens mij al genoeg informatie over gehad. Welke container ik overigens aanraad is de volgende van het [google]sphoof[/google] framework:

<?php
/**
* This file is part of the Sphoof framework.
* Copyright (c) 2010, Sphoof
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. You can also view the
* LICENSE file online at http://www.sphoof.nl/new-bsd.txt
*
* @category Sphoof
* @copyright Copyright (c) 2010 Sphoof (http://sphoof.nl)
* @license http://sphoof.nl/new-bsd.txt New BSD License
* @package Container
*/

/**
* Exception that will be thrown upon encountering an unknown scalar parameter.
*
* @package Container
* @subpackage Exception
*/
class SpUnknownScalar extends SpException { }

/**
* Exception that will be thrown upon encountering an unresolvable parameter.
*
* @package Container
*/
class SpUnknownDependency extends SpException { }

/**
* Exception that will be thrown upon requesting a class that does not exist.
*
* @package Container
*/
class SpUnknownClass extends SpException { }

/**
* Exception that will be thrown upon registering an injecting method that does not exist.
*
* @package Container
*/
class SpUnknownSetterMethod extends SpException { }

/**
* Exception that will be thrown upon requesting an interface that has no
* concrete implementation.
*
* @package Container
*/
class SpUnknownImplementation extends SpException { }

/**
* An exception thrown when using incorrect arguments.
*
* @package Container
*/
class SpInvalidArgumentException extends SpException { }

/**
* The dependency injection container.
*
* @package Container
*/
class SpContainer {
/**
* An optional context to look into.
*
* @var SpContainer
*/
protected $context;

/**
* An array of instances
*
* @var array
*/
protected $instances;

/**
* An array of scalar values.
*
* @var array
*/
protected $scalars;

/**
* An array of implementations.
*
* @var array
*/
protected $implementations;

/**
* An array of ReflectionClass instances.
*
* @var array
*/
protected $reflectedClasses;

/**
* An array of ReflectionMethod instances.
*
* @var array
*/
protected $reflectedMethods;

/**
* An array of class-specific overwrites.
*
* @var array
*/
protected $overwrites;

/**
* An array of methods to inject into after instantation.
*
* @var array
*/
protected $injectMethods;

/**
* Construct the container.
*
* @param SpContainer $context
*/
public function __construct( SpContainer $context = null ) {
$this->context = $context;
}

/**
* Creates a new instance of class $classname
*
* @param string $classname
* @return object
*/
public function create( $classname ) {
if( !$this->isAbstract( $concrete = $this->concrete( $classname ) ) ) {
return $this->injectSetters(
$this->build(
$this->reflect( $concrete ),
$this->resolve( $concrete, $this->parameters( $this->constructor( $concrete ) ) )
)
);
}
}


/**
* Returns an object of the specified type or one of it's concrete implementations.
*
* @param String $abstract
* @return Object
* @throws SpUnknownDependency if a class or one of it's dependencies could not be found.
*/
public function get( $abstract, $requester = null ) {
if( ( $abstract = strtolower( $abstract ) ) && $this->exists( $concrete = $this->concrete( $abstract, $requester ) ) ) {
if( ( $object = $this->instance( $concrete ) ) ) {
return $object;
}
throw new SpUnknownImplementation( 'Could not find implementation for ' . $abstract );
}
throw new SpUnknownClass( sprintf( 'Could not find the class %s', $abstract ) );
}

/**
* Creates a subcontainer which can be further configured and override specific values.
*
* @return SpContainer
*/
public function getSubcontainer( ) {
return new SpContainer( $this );
}


/**
* Tell the container to call and inject $methods on classes of type $classname.
*
* @param string $classname
* @param string|array $methods
* @return SpContainer
*/
public function injectMethods( $classname, $methods ) {
$this->injectMethods[$this->concrete( $classname )] = (array) $methods;
return $this;
}

/**
* Registers an instance to use for class $abstract.
*
* @param string $abstract
* @param object $concrete
* @return SpContainer
*/
public function registerInstance( $abstract, $concrete ) {
if( is_object( $concrete ) && is_string( $abstract ) ) {
$this->instances[$this->concrete( $abstract )] = $concrete;
return $this;
}
throw new SpInvalidArgumentException( );
}

/**
* Sets the scalar values a class that should be passed onto the class.
*
* @param String $classname
* @param Array $scalars
* @return SpContainer
*/
public function setScalars( $classname, Array $scalars ) {
$this->scalars[strtolower( $classname )] = $scalars;
return $this;
}

/**
* Specifies which concrete implementation of an abstract class, base class or interface should be used.
*
* @param String $abstract
* @param String $concrete
* @return SpContainer
*/
public function useImplementation( $abstract, $concrete, $forClass = null ) {
if( null !== $forClass ) {
$this->overwrites[strtolower( $forClass )][strtolower( $abstract )] = strtolower( $concrete );
return $this;
}
$this->implementations[strtolower( $abstract )] = strtolower( $concrete );
return $this;
}

/**
* Tries to instantiate the class $class with parameters $parameters.
*
* @param ReflectionClass $class
* @param array $parameters
* @return object
*/
protected function build( ReflectionClass $class, $parameters ) {
return count( $parameters ) > 0 ? $class->newInstanceArgs( $parameters ) : $class->newInstance( );
}

/**
* Determines which concrete value should be injected into the class $requester.
*
* @param string $abstract
* @param string $requester
* @return string
*/
protected function concrete( $abstract, $requester = null ) {
if( false === ( $overwrite = $this->overwrite( $abstract, $requester ) ) ) {
if( ( $abstract = strtolower( $abstract ) ) && isset( $this->implementations[$abstract] ) ) {
return $this->concrete( $this->implementations[$abstract] );
}
return strtolower( $abstract );
}
return $overwrite;
}

/**
* Gets and returns the constructor for the class $classname.
*
* @param string $classname
* @return ReflectionMethod
*/
protected function constructor( $classname ) {
return $this->constructors[$classname] = $this->reflect( $classname )->getConstructor( );
}

/**
* Determines whether or not the class with the name $class exists.
*
* @param string $class
* @return boolean
*/
protected function exists( $class ) {
return ( class_exists( $class ) || interface_exists( $class ) );
}

/**
* Tries to find a classname for the passed parameter $parameter.
*
* @param Reflectionparameter $parameter
* @return String
*/
protected function findClass( ReflectionParameter $parameter ) {
try {
return $parameter->getClass( );
}
catch( ReflectionException $e ) {
throw new SpUnknownDependency( $e->getMessage( ) );
}
}

/**
* Determines whether or not an instance of class $concrete was already made.
*
* @param string $concrete
* @return boolean
*/
protected function has( $concrete ) {
return isset( $this->instances[$concrete] );
}

/**
* Determines wether or not there is a scalar value to inject.
*
* @param string $classname
* @param string $scalar
* @return boolean
*/
protected function hasScalar( $classname, $scalar ) {
$classname = strtolower( $classname );
return isset( $this->scalars[$classname][$scalar] ) ? $this->scalars[$classname][$scalar] : null;
}

/**
* Tries to find methods that start with "set", and tries to inject the
* correct values into those methods.
*
* @param Object $object
* @return Object
*/
protected function injectSetters( $object ) {
if( ( $classname = $this->concrete( get_class( $object ) ) ) && isset( $this->injectMethods[$classname] ) ) {
foreach( $this->injectMethods[$classname] as $method ) {
if( !method_exists( $object, $method ) || !( $reflectedMethod = $this->method( $classname, $method ) ) ) {
throw new SpUnknownSetterMethod( sprintf( 'Method %s does not exist in class %s', $method, $classname ) );
}
$reflectedMethod->invokeArgs( $object, $this->resolve( $classname, $this->parameters( $reflectedMethod ) ) );
}
}
return $object;
}

/**
* Creates or retrieves an instance of type $abstract, to inject into $requester
*
* @param string $abstract
* @param string $requester
* @return object
*/
protected function instance( $abstract, $requester = null ) {
if( ( $concrete = $this->concrete( $abstract, $requester ) ) && !$this->has( $concrete ) ) {
if( ( $object = $this->create( $concrete ) ) ) {
return $this->instances[strtolower( $abstract )] = $object;
}
return isset( $this->context ) ? $this->context->get( $abstract ) : false;
}
return $this->instances[$concrete];
}

/**
* Determines whether or not a class is either an abstract class or an interface.
*
* @param string $classname
* @return boolean
*/
protected function isAbstract( $classname ) {
return $this->reflect( $classname )->isAbstract( ) || $this->reflect( $classname )->isInterface( );
}

/**
* Creates and caches a reflection method.
*
* @param string $classname
* @param string $method
* @return ReflectionMethod
*/
protected function method( $classname, $method ) {
return $this->reflectedMethods[$classname][$method] = new ReflectionMethod( $classname, $method );
}

/**
* Retrieves a potentially overwritten value, or false if there is no
* overwrite.
*
* @param string $abstract
* @param string $requester
* @return string|false
*/
protected function overwrite( $abstract, $requester ) {
$abstract = strtolower( $abstract );
$requester = strtolower( $requester );
return isset( $this->overwrites[$requester][$abstract] ) ? $this->overwrites[$requester][$abstract] : false;
}

/**
* Returns an array of ReflectionParameters, or an empty array if there are
* none.
*
* @param ReflectionMethod $method
* @return Array
*/
protected function parameters( $method ) {
return ( $method instanceof ReflectionMethod ) ? $method->getParameters( ) : array( );
}

/**
* Returns a ReflectionClass for class $classname
*
* @param string $classname
* @return ReflectionClass
*/
protected function reflect( $classname ) {
if( !isset( $this->reflectedClasses[$classname] ) ) {
$this->reflectedClasses[$classname] = new ReflectionClass( $classname );
}
return $this->reflectedClasses[$classname];
}

/**
* Loops through the parameters of a given method and tries to resolve the
* values.
*
* @param string $classname
* @param array $parameters
* @return array
*/
protected function resolve( $classname, $parameters ) {
foreach( $parameters as $parameter ) {
if( $value = $this->value( $classname, $parameter ) ) {
$values[] = $value;
}
}
return isset( $values ) ? $values : array( );
}

/**
* Retrieves a scalar value for a class, returns null if it optional and not set.
*
* @param string $classname
* @param ReflectionParameter $parameter
* @return mixed
*/
protected function scalar( $classname, ReflectionParameter $parameter ) {
if( ( $scalar = $this->hasScalar( $classname, $parameter->getName( ) ) ) || $parameter->isOptional( ) ) {
return ( null !== $scalar ) ? $scalar : null;
}
throw new SpUnknownScalar( sprintf( 'Unknown scalar values "%s" on class "%s"', $parameter->getName( ), $classname ) );
}

/**
* Tries to find the value for parameter $parameter, which can be either an
* object or a scalar value.
*
* @param string $classname
* @param ReflectionParameter $parameter
* @return mixed
*/
protected function value( $classname, ReflectionParameter $parameter ) {
if( $class = $this->findClass( $parameter ) ) {
return $this->get( $class->getName( ), $classname );
}
return $this->scalar( $classname, $parameter );
}
}

?>




Mooi verhaal Niels van de Ford :) Op deze manier snap ik een beetje wat een container doet. Maar ik merk dat het feit dat ik geen IT opleiding heb gehad en nooit eerder dit soort design patterns gebruikt heb me wel parten speelt. Ik wil in mijn framework dan ook op een wat simpelere manier te werk gaan. Misschien wel vanuit het zelfde principe, maar dan op een manier dat ik het zelf begrijp. De functie omschrijvingen moeten voor mij dan ook dummy proof zijn. Voorbeeld, $row = $database->select('name, age')->from('users'). Kijk dit is voor mij lekker makkelijk te gebruiken omdat ik precies zie wat er gebeurt. Het moet bij mij vooral simpel en effectief zijn. Ander voorbeeld... in mijn eigen framework zou ik niet willen zeggen Framework_Registry::set('object'), maar gewoon simpel $set('object') en om weer op te halen $get('object'). Zou fantastisch zijn als ik zo'n container ook op zo'n simpele manier kan toepassen. Probleem is alleen dat ik te weinig besef heb van wat het (de container) precies doet en hoe je het in de praktijk gebruikt. Maar als jij me kan helpen bij het maken van een hele simpele variant met simpele naamgeving dan zou het me misschien wel lukken...

Op deze manier snap ik een beetje wat een container doet

Een beetje? Je moet het helemaal snappen, want dat was de bedoeling van mijn post. Simpelweg een dependency injection container assembleert je applicatie.


Misschien wel vanuit het zelfde principe, maar dan op een manier dat ik het zelf begrijp

Tja, jouw kennis schiet met de uren omhoog als ik het zo eens zie. Dus wat je nu schrijft is over een aantal uren weer oud en wil je anders doen. Je kan je beter eerst helemaal laten informeren en alles uitzoeken en dit topic nog tweemaal zo lang laten worden en dan pas aan de slag gaan. Ik weet niet of je precies een deadline aan jouw framework hebt zitten? Zo nee dan zou ik het volgende doen de komende dagen / weken:

- Alle gegeven informatie verder onderzoeken en afwegen wat het beste in jouw straatje ligt. Vervolgens pak je een kladblok of whatever en je gaat helemaal uitschrijven hoe het Ozzie framework eruit komt te zien. Tot in het detail.. :) Dikke shizzle allemaal .. Daarna plaats je dat ontwerp hier en geven wij onze complimenten / commentaar. Nadat verbeter / upgrade jij weer heel de bende en laat je het nogmaals controleren totdat er geen negatief commentaar meer wordt geplaatst. (Je hebt natuurlijk wel altijd nog mensen die commentaar geven, maar dat is dan meer persoonlijk) Daarna gooi je heel je framework in de script library en we hebben we een mooie toevoeging in de library :) Die kan wel wat moois gebruiken, na al de rotzooi wat afgelopen maanden is geplaatst. Uitzonderingen daar gelaten uiteraard.

Maar goed, je vroeg om een voorbeeld van het gebruik van een dependency injection container. Laat er nu eentje geschreven zijn door een vriend van mij genaamd: Berry Langerak, klik
Wat je ook gewoon kan doen, is nu een framework maken zoals jij denkt dat het het handigst is. Achteraf zie je dan wat je in het begin anders had kunnen doen. Je maakt dan pas een mooi ontwerp en gaat dat uitwerken. Als je geen idee hebt van wat het ongeveer moet worden, valt er ook niets op papier te tekenen.

En @Niels, leuk verhaaltje hoor ;)
Oke, thanks wederom voor de input.

Ik heb niet echt een deadline... maar wil eigenlijk wel zsm er mee aan de slag :) Om toch nog een wat beter beeld te krijgen... stel je moet een webshop maken. Stel nu dat we even heel simpel zeggen dat we 4 hoofd-onderdelen hebben:

- database
- sessie
- product
- winkelmandje

Oke, normaal gesproken komt er nog meer bij kijken maar ik probeer het idee voor mezelf helder te krijgen :) Momenteel zou ik dit dat ongeveer maken zoals hieronder beschreven. Graag hoor ik van jullie of, waar en waarom je gebruik zou maken van DI (eventueel met een klein voorbeeld). Ik ben benieuwd... :) Hieronder dus zoals ik het nu ongeveer zou doen.

Ik kan me voorstellen dat je een DatabaseModel hebt. In dit model zit een functie die een ini bestandje (dat altijd in een bepaalde folder staat) uitleest waarin de default databasenaam, gebruikersnaam, wachtwoord en host staan. Vervolgens wordt een instanstie gemaakt van de default database die je met de get() functie kunt ophalen (singleton principe dus). Als ik de default database nodig heb zeg ik $database = Database::get() en als ik een select moet doen zou ik zeggen $database->select('id, titel, omschrijving')->from('products')->where('category', $category). Je kunt overigens via de set functie een tweede of derde database aanmaken. Ik geef dan aan de set functie de naam op die ik voor de database wil gebruiken + de naam van het ini bestand waarin de configuratie gegevens staan. Deze database haal ik op via $database2 = Database::get{'Database2'}. Het is niet mogelijk om een database aan te maken die een naam heeft die je al eerder hebt gebruikt. Dan wordt een exception gegooid. Je kunt dus niet 2x Database2 setten.

Voor de sessie gebruik ik gewoon een class Session.php en dit bestand zet ik in m'n library. Alle functies in dit bestand zijn statisch. Wat kun je met deze class? Iets setten, iets getten (met een controle of de key in de sessie wel bestaat), sessie id opvragen, sessie destroyen etc. Stel ik wil het winkelmandje in de sessie zetten dan krijg je bijvoorbeeld Session::set('winkelmandje', $winkelmandje).

Oke, dan de productcontroller... hierin staan acties voor het tonen van een productoverzicht en een productpagina. Afhankelijk van de url, bijvoorbeeld www.mijnsite.nl/product/toon/32/theedoekje :) wordt een product getoond of een compleet productoverzicht. Het ophalen van een product zou ik doen aan de hand van het product id, bijvoorbeeld $row = $database->select('id, titel, omschrijving')->from('products')->where('id', $id).

Voor het winkelmandje zou ik een controller gebruiken met functies om het winkelmandje te tonen en functies om het productaantal op te hogen of te verminderen of een product weg te gooien. Het winkelmandje zou ik dan uit de sessie halen en als er bijvoorbeeld een product verwijderd moet worden dan zou ik dat product verwijderen uit de gegevens die ik uit de sessie heb opgehaald en vervolgens het winkelmandje opnieuw opslaan in de sessie.

Bovenstaande, zij het in dit voorbeeld even wat kort door de bocht, werkt prima... maar nu de cruciale vraag: hoe zou je dit voorbeeld met DI doen? En alsjeblieft... hou het een beetje simpel zodat ik het kan begrijpen :)
Voordat je een applicatie wil maken, heb je eerst een framework nodig...

Met de structuur van je applicatie (het 'domain model', denk aan de klasse 'product') heeft DI niet zo veel te maken. Het is meer het op een handige wijze voorzien van services aan de ondersteunende klassen.

Probeer eerst een (heel basaal) framework te maken, dan pas een applicatie daarbovenop.

Heb je trouwens die tutorialreeks van Fabien Potencier gelezen die ik 2x heb gepost in dit topic?
Ik begrijp dat er een framework moet komen, maar mijn vraag is dus... ervan uitgaande dat dat framework er is... hoe je dan DI toepast op mijn voorbeeld van de webshop zoals hierboven omschreven. Hoe gebruik je DI in dit geval? Voor jou is het gesneden koek, maar ik probeer om de werking ervan te begrijpen zodat ik het DI verhaal uiteindelijk kan meenemen (implementeren) in het framework. Maar dan moet ik dus wel eerst weten (middels een voorbeeldje) hoe je het toepast.

Ja ik heb de tutorial bekeken, maar deze is voor mij behoorlijk (te) abstract en daardoor lastig te begrijpen. Ik moet echt duidelijke concrete omschrijvingen hebben van hoe iets werkt. Denk bijvoorbeeld aan het voorbeeld van Niels met de T-Ford. Door dat soort verhalen begrijp ik steeds beter waar het nou eigenlijk over gaat. (Hou alsjeblieft in gedachten dat ik geen IT opleiding heb gevolgd en ik sommige zaken daardoor minder snel begrijp dan iemand die wel een IT achtergrond heeft of meer ervaring op dit gebied.)

Hou alsjeblieft in gedachten dat ik geen IT opleiding heb gevolgd en ik sommige zaken daardoor minder snel begrijp dan iemand die wel een IT achtergrond heeft of meer ervaring op dit gebied

Dit zeg je haast elke post :) Je kan het gewoon aanleren het is niet iets wat je hokuspokus erin gepompt krijgt :) Wat dacht je hoe een leraar het doet?
Ik weet het, programmeren is in het begin niet gemakkelijk en daardoor haken er veel af. Je moet gewoon veel herhalen, op ten duur valt het kwartje.

Over die voorbeelden: klik.

Reageren