Nu heb ik verzonnen dat ik een class 'core' heb die dingen afhandeld als berichtgeving naar de gebruiker, of debug info etc.
om nu gebruik te kunnen maken van de functions in 'core' laat ik iedere andere class 'core' extenden, maar nu komt het: hoe zorg ik er voor dat alle extendende classes dezelfde instantie van 'core' gebruiken zodat alle berichten bij elkaar uitkomen?
ik zat te denken aan singleton, maar ik heb gelezen dat dit meestal niet nodig is en anders toch wel geen idee is ivm beperkingen die dan optreden.
of is er nog een andere (betere) optie?
bij voorbaat alvast denk voor het lezen van m'n vraag
Ivar
PS als je iets niet snapt aan mijn vraag vraag het dan, dan kan ik het uitleggen!
Ik maak persoonlijk veel gebruik van een registry waar je je referenties van een object in bewaard ( add() ), kijkt of een object bestaat ( exists() ), of ophaald ( get() ).
De registry is dan een singleton object, en is abstract.
Je kan dus altijd je referenties terug vinden door bijvoorbeeld $oCore = Registry::get('Core') op te vragen.
Combineer deze aanpak met $_SESSION en serialize() en je hebt een vergaarbak van referenties, let wel op dat je niet te veel in je registry gaat zetten natuurlijk ;)
Als je behoefte hebt aan een simpele uitwerking van mij registry roep je maar.
function __construct()
{
$this->_oCore = CCore::instance();
}
}
?>
Werkt prima.
core kan bij user en user bij core. Er is steeds maar 1 instantie van core.
Zo kun je ook een winkelmand en een product klasse maken (net als user). Klasse winkelmand doet iets met producten. Winkelmand kan in deze constructie gebruikt maken van klasse product en andersom (die alles via core).
@midas: idd dat bedoel ik.
@hipska: de oplossing die je aandraagt zou wel eens het makkelijkste/best kunnen zijn.
@satsume: ik weet niet ofdat ik wel een registry wil gebruiken, is dit niet een beetje een 'vieze' methode voor dit soort dingen?
@Martijn!: ik bedoelde in eerste instantie idd singleton, maar ik ga nu als eerste eerst de optie van hipska bekijken en eventueel daarna die van jou.
@satsume: ik weet niet ofdat ik wel een registry wil gebruiken, is dit niet een beetje een 'vieze' methode voor dit soort dingen?
Absoluut niet, als je al je instanties en aanroepingen daarvan aan de registry overlaat heb je praktisch het zelfde als een singleton, alleen kijkt de registry of er al een instantie van een object bestaat en niet het object zelf. Sterker nog ben ik van mening dat niet alle (als je er meer hebt waar ik donder op zeg/ga zeggen) objecten de functies moeten bevatten om zich als singleton te gedragen, dat is naar mijn mening niet hun plaats.
Een registry vangt dit op door zelf te kijken of er al een instantie van een object bestaat en die eventueel te retourneren, waar jij denkt dat je een nieuwe maakt, overigens als je wel een nieuwe instantie nodig hebt van een oibject kan je natuurlijk forcen of een andere naam mee geven voor dit object.
@satsume, je zei dat je nog wel een klein voorbeeld kon geven van je registry class. ik zou deze graag even zien, omdat ik even wil kijken of dat het echt zoveel simpeler is als dat je zegt (er zal vast een kern van waarheid in zitten).
zou je ook nog andere voorbeelden kunnen geven waarvoor ik dat registry dan zou kunnen gebruiken?
Een registery is eigenlijk een soort global scope, maar dan eentje die je wat beter kan beheren doordat je toegang kan regelen met methods. Je kan het gebruiken voor alle objecten, naja, eigen alles wat wordt gedeeld binnen je hele webapplicatie.
Vaak wordt een registery als een singleton klasse gebouwd, zodat er maar één centraal register is.
Heel heel heel simpel:
<?php
class Registery {
static public function sharedInstance() {
static $instance;
return $instance ? $instance : $instance = new self();
}
protected $_items = array();
protected function __construct() {
// protected puur om singleton af te dwingen
}
public function set($key, $value) {
$this->_items[$key] = $value;
}
public function get($key) {
if(!isset($this->_items[$key])) throw new InvalidArgumentException("Het register bevat niets met de naam $key");
return $this->_items[$key];
}
}
class DB {
}
$registery = Registery::sharedInstance();
$registery->set('db', new DB());
Je kan het nadeel ook al een beetje zien, wanneer je deze code in je klassen gebruikt, hebben die klassen altijd een register nodig, en moet dat register altijd die variabele bevatten. Op deze manier kan je dus niet voor klasse a, die het registery gebruikt, database a pakken en voor klasse b, die datzelfde registery gebruikt database b. Tenzij je je registery gaat aanpassen tussen de calls door.
Nog een nadeel is dat de klassen die je registery gebruiken op deze manier altijd afhankelijk zijn van het beschikbaar zijn van de klasse Registery. In theorie maakt dit je klassen minder herbruikbaar, maar in praktijk valt dit in mijn ervaring wel mee.
Wat ikzelf dan wel weer een nadeel vindt is dat je niet aan de aanroep naar de klasse, of aan de buitenkant, alle methods en hun argumenten bij elkaar, kan zien wat de klasse nu werkelijk precies nodig heeft. De API maakt niet duidelijk dat hij ook nog informatie haalt uit een register.
Het eerste en het laatste is deels op te lossen door het Singleton deel weg te laten, en één registery-instance mee te geven aan de __construct. Dan heb je er al meer controle over, maar dan is ook een groot deel van het nut weg, en of het overgebleven nut dan nog opweegt tegen het niet kunnen zien wat de klasse nodig heeft aan de API (de API beschrijft niet wat de inhoud moet zijn van je registery) is dan nog maar de vraag.
Moet je nu geen singleton of registery gebruiken? Dat is helemaal aan jezelf. Ik zelf probeer ze altijd te vermeiden, en je kan heel goed zonder leven heb ik gemerkt, al zal je altijd een soort context-object nodig hebben, een object dat toegang geeft tot bijvoorbeeld de data uit je model wil je MVC deels implementeren. Maar singleton gebruiken is veel minder denkwerk. Je zou kunnen beargumenteren dat dit tot minder mooie code leidt, maar volgens mij valt dat wel mee. Vooral in het begin is het erg handig, in de zin van een gemakkelijke oplossing voor veel problemen die je tegenkomt bij het programmeren a la OOP. En of de nadelen op jouw en je applicatie van toepassing zijn, ligt helemaal aan je eigen eisen :)