Hi,

Ik zit me af te vragen hoe ik op een transparante manier object het best kan doorgeven. Echter wil ik er voor zorgen dat de klassen niet afhankelijk van mekaar worden. Ik denk dat ik daar momenteel vrij goed in slaag. Alleen, ik ben er nog niet geheel uit. Ik zoek dus meningen, en eventuele alternatieven.

Ik ben bezig met het ontwikkelen van een klein simpel framework. Het framework is opgebouwd volgens het MVC principe. Alle requests komen binnen op mijn 'FrontController'. Deze bepaalt dan welke end controller er gebruikt moet worden, welke actie er uit gevoerd moet worden, paramaters...

Om de resources netjes te gebruiken, heb ik in mijn FrontController gebruik gemaakt van een Service Container. Deze houdt o.a. de log-service bij en de database-service. Deze worden dan overgedragen naar de uiteindelijke controllers, dus volgens mij zit dat goed qua afhankelijkheden en resources.

Verder heb ik ook gebruik gemaakt van interfaces. Bijvoorbeeld, de klasse database verwacht een parameter (via de constructor) ConfigInterface, zodanig dat ik vrij ben wat soort config object ik nu eigenlijk meegeef. Zolang het maar de ConfigInterface implementeert. Hierdoor creëer ik volgens mij voldoende flexibiliteit.

Ik vraag me af of dit dus een nette manier is.
Kortom gewoon een plek waar de services gedefineerd zijn. In een config bestand bijvoorbeeld zo:


database
	class = \PDO
	host = localhost
	usernaam = root
	ww = wachtwoord
	database = db1
storage
	class = Framework\Blabla\PDOStorage
	db = database
...



horen alle mapper hier ook in? dus:

userMapper
	class = Namespace\Mapper\...\UserMapper
	storage = storage


En waar hoort dit bestand? In de app map of in de framework map?
Hmmz inderdaad, ik vraag me ook af hoe dat dan zit. Momenteel heb ik in mijn front controller iets staan als:


<?php
        try {

            $this->container = new ServiceContainer();
            $this->container->set('logger.class', 'DebugLog');
            //$this->container->set('logger.file', $_SERVER['DOCUMENT_ROOT'] . '/error_log');
            $this->container->set('logger', function($c) {
                        $class = $c->get('logger.class');
                        //return new $class($c->get('logger.file'));
                        return new $class();
                    }, true);

            $this->logger = $this->container->get('logger');
            $this->logger->error('<h1>Debuglogger</h1>');
        } catch (Exception $e) {
            echo 'fatal error';
        }
        try {
            $this->container->set('configparser.class', 'JsonParser');
            $this->container->set('configparser.file', $this->getAbsolutePath() . '/config.json');
            $this->container->set('configparser', function($c) {
                        $class = $c->get('configparser.class');
                        return new $class($c->get('configparser.file'));
                    }); //not needed to share

            $this->container->set('config.class', 'Config');
            $this->container->set('config', function($c) {
                        $class = $c->get('config.class');
                        return new $class($c->get('configparser'));
                    });

            $this->container->set('database.class', 'Database');
            $this->container->set('database.config', $this->container->get('config'));
            $this->container->set('database.logger', $this->container->get('logger'));
            $this->container->set('database', function($c) {
                        $class = $c->get('database.class');
                        return new $class($c->get('database.config'));
                    }, true);

            $this->container->set('form.class', 'Form');
            $this->container->set('form', function($c) {
                        $class = $c->get('form.class');
                        return new $class();
                    }, true);

            $this->container->set('template.class', 'Template');
            $this->container->set('template.layout', 'default');
            $this->container->set('template', function($c) {
                        $class = $c->get('template.class');
                        return new $class($c->get('template.layout'), $c->get('form'));
                    });
            $this->parseUri();
        } catch (Exception $e) {
            $this->logger->critical($e->getMessage());
        }
?>
Staat dat zo in je front-controller? Ik dacht dat je dat allemaal in een appart bestand moest instellen. Je moet de configuratie en de verwerking splitsen. Dat is wat ik toch heb afgeleid van dit topic.
Dit stukje code staat inderdaad in een ander bestand :-). Maat technisch gezien, staat het dus wel in mijn front controller. Dat je het opsplitst in meerdere bestanden, is naar mijn mening eerder voor de duidelijkheid. Doe je dat niet, dan is dat ook geen ramp, alleen minder netjes.
Oke daar ben ik het met eens. Ik ga mijn config waarschijnlijk uit een .yml lezen (ben er nog mee aan het experimenteren) misschien is dat ook een optie?
Dat is een keuze dat je maakt natuurlijk. Zelf ga ik voor Json. Leesbaar & compact formaat. Verder wil ik ook delen van mijn applicatie uitwisselbaar maken, en dan is Json ook welkom. Verder een koud kunstje om van json naar XML te gaan :-)
Oké, wat je kunt doen is gebruik maken van een config bestandje. Hiervoor deel je het op in 2 config bestandjes: 1 voor de Applicatie (in bijv. config/services.yml) en 1 voor het Framework (ergens in de framework map).

Hoe ik zo'n configuratie bestand eruit zou laten zien en hoe je dat moet parsen heb ik zojuist in andere topics verteld: http://www.phphulp.nl/php/forum/topic/dependency-injection/89060/#639305 (vanaf deze reactie en verder)

Wat je ook kan doen is ServiceProviders maken. Een voorbeeldje daarvan kun je zien in Silex of in een applicatie van mij: Inspector. Hier zie je dat de providers worden aangeroepen, hoe deze providers eruit zien kun je hier bekijken.
Het enige punt dat ik dan nog zie, je geeft aan je provider een config mee. Je config, die wordt geparsed door een 'config parser', en daarna gebruik je een 'config class'. Eigenlijk dus ook een service. Deze heb je dan wel dubbel, tenzij je deze eerst aan je service container toevoegd. Al zie ik daar het nut niet van in, aangezien je deze specifieke config niet meer op een andere plaats gaat gebruiken.

Of zie ik dat helemaal verkeerd?

Reageren