PHP Factory & Singleton pattern

Pagina: 1
Acties:
  • 118 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb in PHP de volgende files:

iDatabase - interface voor database modules
DatabaseFactory - Geeft instance van gewenste database class terug (SINGLETON)
MySQLDatabase - Database class implements iDatabase

Nu laat ik de factory de instance teruggeven. Als de instance er al is, geeft ie de bestaande instance terug. Maar als ik de pagina refresh blijft hij nieuwe instances maken. Waarom werkt mijn singleton niet?

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class DatabaseFactory
{
    function &getInstance ($class)
    {
        //Array om instances vast te houden
        static $instances = array();
        
        //Als de opgevraagde class nog niet bestaat
        if (!array_key_exists($class, $instances))
        {
            //Class instantie maken
            require_once ($class .'.php');
            $instances[$class] = new $class;
        }
        
        //Class instance terug geven
        $instance =& $instances[$class];                
        return $instance;            
    }
    
}


Misschien pas ik het pattern niet helemaal goed toe. Ik heb het wel eens toegepast in Java en toen ging het goed...Of kan PHP geen objecten vasthouden omdat het stateless is? (sessies?)

[ Voor 3% gewijzigd door Verwijderd op 24-10-2007 14:13 ]


Acties:
  • 0 Henk 'm!

  • GX
  • Registratie: Augustus 2000
  • Laatst online: 14-05 09:40

GX

Nee.

PHP onthoudt uit zichzelf geen state van je objecten; dus als de pagina klaar is met renderen word ieder bestaande object vernietigd.

Je kan natuurlijk spelen met $_SESSION om dingen over pagina's heen te slepen of zelfs een leuk systeempje bedenken.

[ Voor 31% gewijzigd door GX op 24-10-2007 14:18 ]


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 02:21

Janoz

Moderator Devschuur®

!litemod

php heeft enkel een request scope. Elk request is een proces op zichzelf. Een singleton pattern zoals dat in java wel mogelijk is kan niet in php. Ookal zou je sessies gebruiken, dan nog blijft je object niet 'leven'. Bij sessies worden de gegevens geserialiseerd naar de schijf en bij het volgende re4quest weer gedeserialiseerd. Een database verbinding kun je niet serialiseren.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Dus die singleton is vooral handig als ik meerdere database acties vanuit dezelfde pagina doe?
Dan weet ik zeker dat er maar 1 connectie open staat.

Janoz:
Vreemd, aangezien er wel veel te vinden is:
http://www.google.com/search?hl=en&q=php+singleton

[ Voor 25% gewijzigd door Verwijderd op 24-10-2007 14:20 ]


Acties:
  • 0 Henk 'm!

  • FragFrog
  • Registratie: September 2001
  • Laatst online: 09:34
Janoz schreef op woensdag 24 oktober 2007 @ 14:19:
Een database verbinding kun je niet serialiseren.
Klopt, maar in additie, je kan hem wel persistant maken. Zie de persistant connection opties van PHP :)

Overigens zorgt PHP er default zelf ook al voor dat je maar 1 connection gebruikt bij meerdere queries op een zelfde database (mits die tenminste met dezelfde credentials als de vorige connectie aangeroepen wordt), dus een singleton implementatie is fancy maar overbodig. Probeer het zelf maar eens met x keer achter elkaar echo mysql_connect() aan te roepen :)

Wat betrefd singletons: het kan prima maar enkel binnen je request. Ik gebruik ze zelf vooral in combinatie met een context class loader factory, zorgt ervoor dat elke class alleen geinstantieerd wordt als'ie ook nodig is en dan hooguit 1 keer. Met je database connector kun je'm ook prima gebruiken, maar zoals gezegd, PHP doet dat zelf ookal voor je dus het is een beetje overbodig :+

[ Voor 28% gewijzigd door FragFrog op 24-10-2007 19:38 ]

[ Site ] [ twitch ] [ jijbuis ]


Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Naast wat iedereen boven mij zegt, heb je de variabele waar de database instantie(s) in staan in de getInstance functie gezet. Door de leukigheid genaamd 'scope', betekent dit dat de $instances array niet bestaat buiten die functie: waneer je de functie aanroept wordt hij opnieuw gemaakt, en wanneer de functie afloopt wordt hij weer vrijgegeven (bij wijze van spreken natuurlijk).

De $instances array moet dus buiten je functie definitie, maar binnen je class definitie staan om het singleton pattern proper te maken.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class DatabaseFactory {

   private static $instances = array() ;
   
   public static function &getInstance ($class) {

        //Als de opgevraagde class nog niet bestaat 
        if (!array_key_exists($class, $instances)) 
        { 
            //Class instantie maken 
            require_once ($class .'.php'); 
            $instances[$class] = new $class; 
        } 
         
        //Class instance terug geven 
        $instance =& $instances[$class];                 
        return $instance;  
  } 

}


(Of ik heb het fout en het gebruik van de static modifier binnen functies in PHP maakt er een static var buiten de scope van de functie van. In dat geval, negeer dit :+ )

Acties:
  • 0 Henk 'm!

  • FragFrog
  • Registratie: September 2001
  • Laatst online: 09:34
Voor zover ik weet heb je zowel gelijk als ongelijk. Gelijk in dat je static buiten een functiedefinitie moet definieren, ongelijk in dat het erin definieeren ongewenst gedrag oplevert, je krijgt namelijk gewoon een error over een undeclared static property ;)

[ Site ] [ twitch ] [ jijbuis ]

Pagina: 1