OOP static class met interface?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Joakim Broden

Joakim Broden

20/07/2012 17:37:10
Quote Anchor link
Ik ben bezig om in OOP een log class te maken, met behulp van een interface. Ik gebruik een interface zo dat ik verschillende logs kan doen, bv een log die het opslaat in een bestand, of een log die het mailt etc. Aller eerst is dit een juiste aanpak of zouden jullie het anders doen? Nu ziet mijn interface er zo uit:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php
interface Logger {
    /**
     * @acces public.
     */

    public static function construct();
    
    /**
     * @acces public.
     * @param $message String.
     */

    public static function config($message = null);
    
    /**
     * @acces public.
     * @param $message String.
     */

    public static function info($message = null);
    
    /**
     * @acces public.
     * @param $message String.
     */

    public static function fine($message = null);
    
    /**
     * @acces public.
     * @param $message String.
     */

    public static function warning($message = null);
    
    /**
     * @acces public.
     * @param $message String.
     */

    public static function error($message = null);
    
    /**
     * @acces public.
     * @param $level String.
     * @param $debug String.
     * @param $message String.
     */

    public static function log($level = null, $debug = null, $message = null);
}

?>


Nu maak ik gebruik van een log die alles opslaat in een bestand met de code:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
    LoggerFile::construct(dirname(__FILE__).'\..\..\data\logs\error-log.php');
?>


Nu is mijn vraag: Wat als ik een log wil maken die mij alles e-mailt. Moet ik dan overal in mijn website LoggerFile veranderen naar LoggerEmail (LoggerEmail is natuurlijk weer een class). Maar is hier geen betere manier voor, zodat ik maar met een geringe aanpassing de log kan veranderen van LoggerFile naar LoggerEmail? Het gaat om een static class zodat ik overal en makkelijk de log kan aanroepen.
 
PHP hulp

PHP hulp

28/11/2024 18:31:16
 
Eddy E

Eddy E

20/07/2012 17:57:18
Quote Anchor link
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
log("email", "Dit ging goed");
?>


Kan toch in 1 functie?
Met __LINE__ en __FILE__ en __DIR__ etc kan je precies vinden welke regel het is.
 
Erwin H

Erwin H

20/07/2012 18:04:44
Quote Anchor link
Ik zou er geen static class van maken, maar gewoon een normale class.
Zelf heb ik bijvoorbeeld een log class die zichzelf registreert bij elke class in mijn applicatie als een observer. Elke class zelf kan vervolgens een interne functie aanroepen (die is aangemaakt in een abstracte basis class waar alle classes van afstammen) die vervolgens de log aanroept om de melding te doen. De log class vervolgens heeft weer een soort mapper erachter die de boel opslaat. Op die manier kan elke class een melding genereren en wordt het ofwel opgeslagen in een database (als die beschikbaar is), ofwel in een tekst bestand.
 
Wouter J

Wouter J

20/07/2012 18:19:01
Quote Anchor link
Ik gebruik altijd het die dat Jelmer hier mooi heeft weergegeven: http://www.phphulp.nl/php/forum/topic/de-opbouw-van-een-logging-class/81508/#577390

En hertog, ja. Als je het nu wilt veranderen dan zul je overal alleen het initializen moeten aanpassen. Dat is natuurlijk niet zo handig. Vandaar dat je het Dependency Injection pattern moet gebruiken, of meer preciezer een Service Container:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
// bootstrap
$container = new Container();

$container->set('logger.class', 'FileLog');
$container->set('logger', function($c) {
    return new $c->get('logger.class')();
});


// in je code
$logger = $container->get('logger');
$logger->log('the message', LOG::LEVEL_ERROR);
?>

Zo hoef je alleen in de bootstrap logger.class aan te passen. Meer hierover: http://www.phphulp.nl/php/tutorial/classes/dependency-injection/760/ en http://fabien.potencier.org/article/11/what-is-dependency-injection en http://fabien.potencier.org/article/12/do-you-need-a-dependency-injection-container

@Eddy, natuurlijk alles kan in flat PHP of met een functie. Maar niet zo flexibel als het nu is, en natuurlijk niet zo mooi.
 
Joakim Broden

Joakim Broden

20/07/2012 19:02:51
Quote Anchor link
Bedankt voor de antwoorden hier kan ik wat mee :-)

In die Service Container kan ik bv alles in zetten zoals database, config, logger etc zoals je in dit topic al aangaf http://www.phphulp.nl/php/forum/topic/oop-config-class/85756/
 
Wouter J

Wouter J

20/07/2012 19:14:09
Quote Anchor link
Ja, een service container is een verzameling (container) van services. Bij services moet je je taken voorstellen zoals inderdaad een Config service, een Database service, een logger service, enz.

Elke service krijgt zijn eigen properties (in het geval hierboven logger.class) en elke service krijgt op zijn minst 1 functie (logger) om zichzelf aan te maken. Maar het voorbeeld hierboven is heel erg simpel. Mooiere voorbeelden van het gebruik van service containers: http://www.phphulp.nl/php/forum/topic/pad-ophalen-in-oop/84167/#599080 of http://www.phphulp.nl/php/forum/topic/ontwerpen-usermanagement/85413/#610232
 
Joakim Broden

Joakim Broden

20/07/2012 20:53:40
Quote Anchor link
Bedankt, ik heb nu zo'n service container gemaakt en werkt :) Zoals:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php
    $this
->container->setContainer('config.class', 'Config_ConfigParserINI');
    $this->container->setContainer('config.config.ini', dirname(__FILE__).'/../../config.ini');
    $this->container->setContainer('config', function($container) {
        $class = $container->getContainer('config.class');
                
        $config = new $class();
        return $config->parseConfigByFile($container->getContainer('config.config.ini'));
    });

?>


1 ) Stel ik heb het volgende: Ik heb een userMapper en die heeft de config class en database class nodig. Wat is dan beter, de volledige $this->container of $this->container->getContainer('config') en $this->container->getContainer('database') mee te geven aan de constructor?

2 ) Als ik 5x $this->container->getContainer('config')->getConfig('database.name') doe, zoals ik dan begrijp uit mijn logica word er 5x een new Config() gedaan? Dat lijkt mij niet de bedoeling toch? Of is de bedoeling om dit te doen (bedoel je dat met 'en elke service krijgt op zijn minst 1 functie (logger) om zichzelf aan te maken.'):
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?php
    $this
->container->setContainer('config.class', 'Config_ConfigParserINI');
    $this->container->setContainer('config.config.ini', dirname(__FILE__).'/../../config.ini');
    $this->container->setContainer('config.constructor', function($container) {
        $class = $container->getContainer('config.class');
                
        $config = new $class();
        return $config->parseConfigByFile($container->getContainer('config.config.ini'));
    });

    $this->container->setContainer('config', $this->container->getContainer('config.constructor'));
?>


3 ) En is mijn logger aanpak goed wat betreft het gebruik van een interface?
Gewijzigd op 20/07/2012 21:46:31 door Joakim Broden
 
Wouter J

Wouter J

20/07/2012 23:21:23
Quote Anchor link
1) Je hebt weer even een verkeerde naamgeving, maakt niet uit je leert het van zelf wel. Je hebt 1 container ($this->container in dit geval) en die heeft verschillende services/properties je je meegeeft. Deze zijn geen nieuwe container, dus geen setContainer method maar een set method om een waarde te zetten.
Maar om te antwoorden 2x de aparte meegeven is het beste. En misschien de mapper ook nog ContainerAware maken, zodat we getContainer in de Mapper kunnen aanroepen.
Lees anders ook die tutorial van Pim die ik je gaf, die legt dit allemaal uit.

2) Ja dat klopt en dat is natuurlijk niet jou bedoeling. Vandaar dat we iets moeten maken wat een shared service heet. Ook dit heeft Pim beschreven.

Ik zou ook i.p.v. je eigen container pimple gebruiken. Dit is een mooie container met alles er al in

3) je interface is goed, al zou ik al dat static weghalen

En even de code die je hier geeft is niet helemaal goed. Als config.constructor en config gelijk zijn, waarom dan niet die 2 samenvoegen en in 1 keer config maken?
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.