Toon posts:

[PHP4] Singeleton implementatie werkt niet correct

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben voor het eerst bezig om een redelijk groot project te realiseren in Classes (wens van klant).
Om er voor te zorgen dat (sommige) objecten maar een keer gecreerd worden maak ik gebruik van de PHP singleton implementatie.

Mijn probleem kan ik het beste uitleggen met een stuk vrij simpele code:
PHP:
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
47
48
49
50
<?php
class testClass
{
    var $testVar;
    
    //constructor
    function testClass()
    {
        $this->testVar = "Hallo wereld";            
    }
    
    //singleton implementatie
    function &getInstance()
    {
        static $instance;
                
        if(!isset($instance))       
            $instance = new testClass();
                    
        return $instance;                       
    }   
    
    //set de variable testVar
    function setTest($text)
    {
        $this->testVar = $text; 
    }
    
    //get de vriable testVar
    function getTest()
    {
        return  $this->testVar;         
    }
}

//maak het eerste object
$testObject1 = testClass::getInstance();

//zet de tekst naar aapjes
$testObject1->setTest("Dag aapjes");

//maak het tweede object
$testObject2 = testClass::getInstance();

//print de testObject1 testVar uit
print 'testObject1: '. $testObject1->getTest() . '<br />'; //print "Dag aapjes"

//print de testObject2 testVar uit
print 'testObject2: '. $testObject2->getTest() . '<br />'; //print "Hallo wereld"
?>


De bedoeling is natuurlijk dat de laatste print ook "Dag aapjes" print. De functie getInstance van de class geeft op dit moment een copy terug van instance op het moment dat de functie getInstance werd aangeroepen (snappen jullie het nog :P)

Waarschijnlijk doe ik iets niet goed met de referenties (&)

Als ik "$instance = new testClass();" vervang door "$instance =& new testClass();" dan is op een een of andere reden de static $instance altijd niet geset (isset is altijd false) en wordt er dus altijd het object opnieuw aangemaakt.

Ik heb hier op GoT en op het interweb een beetje rondgekeken, maar ik niet echt een oplossing vinden. (Wel voor PHP5 overigens)

Wat doe ik fout? Of kan dit gewoon niet?

Verwijderd

Je doet volgens mij iets fout, kijk eens goed naar de scope van je 'instance'.

  • Soultaker
  • Registratie: September 2000
  • Nu online
Sowieso ondersteund PHP4 geen references naar objecten (alleen naar variables), maar dat zou hier niet uit moeten maken. Is het niet zo dat je expliciet een reference moet returnen in PHP4, dus return &$instance; op regel 20?

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
  • regel 15 moet in de scope van je class staan, niet in de scope van je functie.
  • regel 13 moet die & weg.
  • regel 20 moet &$instance zijn.
Dan zou het moeten werken denk ik.

Maarre, als je opdrachtgever graag een net OO product wil, dan wil je hem wellicht uitleggen dat PHP5 dan een betere keuze is. PHP4 is redelijk brak met OO.

[ Voor 28% gewijzigd door Grijze Vos op 11-06-2007 14:03 ]

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Verwijderd

Topicstarter
Verwijderd schreef op maandag 11 juni 2007 @ 13:59:
Je doet volgens mij iets fout, kijk eens goed naar de scope van je 'instance'.
Ik heb het voorbeeld overgenomen van http://www.developertutor...pattern-050729/page3.html
Ik weet vrij zeker dat een static variable in de functie moet staan (http://www.php.net/manual/nl/language.variables.scope.php -> static)
Soultaker schreef op maandag 11 juni 2007 @ 13:59:
Sowieso ondersteund PHP4 geen references naar objecten (alleen naar variables), maar dat zou hier niet uit moeten maken. Is het niet zo dat je expliciet een reference moet returnen in PHP4, dus return &$instance; op regel 20?
return &$instance is zelfs een fatal error ;) Maar
code:
1
2
$test =& $instance
return $test

werkt ook niet

edit: ff kijken naar grijze vos z'n comment

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 07:54

Janoz

Moderator Devschuur®

!litemod

Ik weet vrij zeker dat een static variable in de functie moet staan
Ikzelf zeg altijd 'Assumptions are the mother of all fuckups'. In je linkje zie ik nergens staan dat static in een functie moet. Daarnaast lijkt me instance duidelijk iets dat bij de class hoort, niet perse bij de functie.

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


  • Soultaker
  • Registratie: September 2000
  • Nu online
Volgens mij mag die static variable zowel in de class als in de functie staan. De keuze voor de functie scope lijkt me hier prima, want zo kan je 'm niet per ongelijk gebruiken vanuit andere functies voordat 'ie geïnitialiseerd is.

Verwijderd

Topicstarter
Grijze Vos schreef op maandag 11 juni 2007 @ 14:02:
  • regel 15 moet in de scope van je class staan, niet in de scope van je functie.
  • regel 13 moet die & weg.
  • regel 20 moet &$instance zijn.
Dan zou het moeten werken denk ik.

Maarre, als je opdrachtgever graag een net OO product wil, dan wil je hem wellicht uitleggen dat PHP5 dan een betere keuze is. PHP4 is redelijk brak met OO.
regel 15 moet in de scope van je class staan, niet in de scope van je functie.
In PHP 4 kan je geen static in een class maken, dat geeft een parse error

regel 13 moet die & weg.
die is weg

regel 20 moet &$instance zijn.
Geeft ook een parse error

  • Soultaker
  • Registratie: September 2000
  • Nu online
Oh ja, ik weet het al weer: je moet expliciet de reference kopiëren bij assignment:
PHP:
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//maak het eerste object 
$testObject1 =& testClass::getInstance(); 
 
//zet de tekst naar aapjes 
$testObject1->setTest("Dag aapjes"); 
 
//maak het tweede object 
$testObject2 =& testClass::getInstance(); 
 
//print de testObject1 testVar uit 
print 'testObject1: '. $testObject1->getTest() . '<br />'; //print "Dag aapjes" 
 
//print de testObject2 testVar uit 
print 'testObject2: '. $testObject2->getTest() . '<br />'; //print "Dag aapjes" 

Let op het gebruik van =& om bij assignment van een reference te kopiëren in plaats van het object.

Een ampersand bij een return-statement mag inderdaad niet in PHP4. Het feit dat de functie gedeclareert is met een ampersand betekent al dat 'ie een reference returnt, maar je moet dan nog wel expliciet die reference behouden bij assignment aan andere variabelen, anders krijg je alsnog een kopie.

offtopic:
Echt een ontzettend prutssysteem met die references in PHP4. Ik zou er niet object-georiënteerd in willen programmeren. Gebruik dan gelijk PHP5, dan heeft je code ook nog toekomst als support voor PHP4 ophoudt en je met lappen code zit die niet goed werken onder PHP5.

[ Voor 39% gewijzigd door Soultaker op 11-06-2007 14:23 ]


Verwijderd

Topicstarter
Thx Soultaker het volgende werkt even voor de duidelijkheid:
PHP:
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
47
48
49
50
<?php
class testClass
{
    var $testVar;
    
    //constructor
    function testClass()
    {
        $this->testVar = "Hallo wereld";            
    }
    
    //singleton implementatie
    function &getInstance()
    {
        static $instance;
                
        if(!isset($instance))       
            $instance = new testClass();
                
        return $instance;
    }   
    
    //set de variable testVar
    function setTest($text)
    {
        $this->testVar = $text; 
    }
    
    //get de vriable testVar
    function getTest()
    {
        return  $this->testVar;         
    }
}

//maak het eerste object
$testObject1 =& testClass::getInstance();

//zet de tekst naar aapjes
$testObject1->setTest("Dag aapjes");

//maak het tweede object
$testObject2 =& testClass::getInstance();

//print de testObject1 testVar uit
print 'testObject1: '. $testObject1->getTest() . '<br />'; //print "Dag aapjes"

//print de testObject2 testVar uit
print 'testObject2: '. $testObject2->getTest() . '<br />'; //print "Hallo wereld"
?>


offtopic:
[quote]
Echt een ontzettend prutssysteem met die references in PHP4. Ik zou er niet object-georiënteerd in willen programmeren. Gebruik dan gelijk PHP5, dan heeft je code ook nog toekomst als support voor PHP4 ophoudt en je met lappen code zit die niet goed werken onder PHP5.
[/quote]
Het systeem moet op onze server draaien en helaas draaien wij php 4 (een upgrade zit er voorlopig niet in i.v.m. met de vele sites die we hosten)
Janoz schreef op maandag 11 juni 2007 @ 14:12:
[...]
Ikzelf zeg altijd 'Assumptions are the mother of all fuckups'. In je linkje zie ik nergens staan dat static in een functie moet. Daarnaast lijkt me instance duidelijk iets dat bij de class hoort, niet perse bij de functie.
quote van PHP site:
A static variable exists only in a local function scope, but it does not lose its value when program execution leaves this scope.
Ik had het hier over de simpele static. PHP 4 heeft volgens mij niet veel andere.

Overigens staat "toevallig" op dezelfde pagina uitgelegd waarom het volgende niet werkt:
Als ik "$instance = new testClass();" vervang door "$instance =& new testClass();" dan is op een een of andere reden de static $instance altijd niet geset (isset is altijd false) en wordt er dus altijd het object opnieuw aangemaakt.
Quote van PHP site (PHP4):
References are not stored statically Kort maar krachtig

[ Voor 43% gewijzigd door Verwijderd op 11-06-2007 14:31 ]


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 07:54

Janoz

Moderator Devschuur®

!litemod

quote van PHP site:
A static variable exists only in a local function scope, but it does not lose its value when program execution leaves this scope.
Ik had het hier over de simpele static. PHP 4 heeft volgens mij niet veel andere.
Hmm, ik nam aan (ja, weer die assumptions :D ) dat ze het daar puur over global scope vs functionscope hadden (static in de global scope is bij php inderdaad nogal nutteloos). Er wordt in principe daar helemaal niet over object scope gepraat.

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


  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Soultaker schreef op maandag 11 juni 2007 @ 14:20:
Oh ja, ik weet het al weer: je moet expliciet de reference kopiëren bij assignment
Oh idd, dat was de gimmick by PHP4. Long time ago...

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info

Pagina: 1