[PHP] singleton wordt stilzwijgend overschreven

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Matthis
  • Registratie: Juli 2004
  • Laatst online: 13-06 13:45
ik *probeer* het Singleton-pattern te implementeren in m'n project (vnl. om SQL-layer te gebruiken), maar om de een of andere reden lukt het niet zo fijn

Eerst wat code:
het singleton SQL:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function get_sql() 
  {
    static $instance_db; 
    global $db_host, $db_user, $db_password, $db_database, $debug_mode;
   
    if(!isset($instance_db)) { 
        $instance_db = new sql($db_host, $db_user, $db_password, $db_database, $debug_mode);
        echo "new SQL <br>";
    } 
    echo "<pre>";
    print_r($instance_db);
    echo "</pre>";

    return($instance_db); 
 }


m'n testcase:
PHP:
1
2
3
4
5
6
7
8
9
$db = get_sql();
$db->q('select * from config WHERE 1=1');
echo "test: $db->_num_queries";
$db->q('select * from config');

$db2 = get_sql();
$db2->q('select * from config where 2=2');

$db->show_debug_info();

De werking ervan klopt echter niet. Volgens mijn tests wordt er slechts 1x een SQL-object aangemaakt, maar wanneer ik alle uitgevoerde queries opvraag (mbhv show_debug_info()), staan slechts de queries van $db in de uitgevoerde lijst, terwijl er (volgens mij) toch 3 zouden moeten staan (de 2 van $db en deze van $db2)?

Hopelijk kan er iemand me licht in de duisternis brengen...

Acties:
  • 0 Henk 'm!

  • JackBol
  • Registratie: Maart 2000
  • Niet online

JackBol

Security is not an option!

Dan klopt het toch? Omdat get_sql() een singleton is, zal hij hier:
code:
1
$db2 = get_sql();      <---


niet meer gemaakt kunnen worden (want if(!isset($instance_db)) = false)

daardoor wordt de query van db2 toch gediscard?

helaas heb ik hier geen test mysql draaien om even te testen...

De actuele opbrengst van mijn Tibber Homevolt


Acties:
  • 0 Henk 'm!

  • JackBol
  • Registratie: Maart 2000
  • Niet online

JackBol

Security is not an option!

ik heb hier nog een stukje eenvoudige voorbeeldcode (bron: wikipedia)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
class Singleton {
    static private $instance = NULL;
    
    private function __construct() {
    }
    
    static public function getInstance() {
        if (self::$instance == NULL) { 
            self::$instance = new Singleton();
        }
        return self::$instance; 
    }
}


misschien kun je er wat mee. (php5)

De actuele opbrengst van mijn Tibber Homevolt


Acties:
  • 0 Henk 'm!

  • JackBol
  • Registratie: Maart 2000
  • Niet online

JackBol

Security is not an option!

Als je overigens de singleton aan $db2 wilt hangen, zul je eerst $db moeten vernietigen

De actuele opbrengst van mijn Tibber Homevolt


Acties:
  • 0 Henk 'm!

  • Matthis
  • Registratie: Juli 2004
  • Laatst online: 13-06 13:45
Dirk-Jan schreef op maandag 24 oktober 2005 @ 00:49:
daardoor wordt de query van db2 toch gediscard?
De query zou toch niet mogen gediscard worden? enkel de aanmaak van een nieuwe connectie/SQL-object moet vermeden worden, wat ook gebeurt. Maar de query van $db2 zou op het object van $db1 moeten uitgevoerd worden, zodat bv. de totale query-count en query-list kloppen...

Ik vind het raar dat er maar 1 object wordt aangemaakt, maar de query-count niet meegaat.

Acties:
  • 0 Henk 'm!

  • JackBol
  • Registratie: Maart 2000
  • Niet online

JackBol

Security is not an option!

Bij het aanmaken van object $db2 neemt hij het object $db niet over, hij maakt gewoon geen object aan.

[ Voor 4% gewijzigd door JackBol op 24-10-2005 01:02 ]

De actuele opbrengst van mijn Tibber Homevolt


Acties:
  • 0 Henk 'm!

  • Matthis
  • Registratie: Juli 2004
  • Laatst online: 13-06 13:45
hij maakt wel een object aan, dat is het rare juist, kijk dit is de output

HTML:
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
get SQL aangeroepen
new SQL gemaakt

sql Object
(
    [_num_queries] => 0
    [_all_queries] => Array
        (
        )

    [_config] => 
    [_query] => 
    [_debug_mode] => 1
)

QUERY: select * from config WHERE 1=1

Query():

sql Object
(
    [_num_queries] => 1
    [_all_queries] => Array
        (
            [0] => select * from config WHERE 1=1
        )

    [_config] => 
    [_query] => Resource id #9
    [_debug_mode] => 1
)

test: 1

QUERY: select * from config

Query():

sql Object
(
    [_num_queries] => 2
    [_all_queries] => Array
        (
            [0] => select * from config WHERE 1=1
            [1] => select * from config
        )

    [_config] => 
    [_query] => Resource id #10
    [_debug_mode] => 1
)

get SQL aangeroepen

sql Object
(
    [_num_queries] => 0
    [_all_queries] => Array
        (
        )

    [_config] => 
    [_query] => 
    [_debug_mode] => 1
)

QUERY: select * from config where 2=2

Query():

sql Object
(
    [_num_queries] => 1
    [_all_queries] => Array
        (
            [0] => select * from config where 2=2
        )

    [_config] => 
    [_query] => Resource id #11
    [_debug_mode] => 1
)

# queries:2
Query 1: select * from config WHERE 1=1
Query 2: select * from config

Acties:
  • 0 Henk 'm!

  • JackBol
  • Registratie: Maart 2000
  • Niet online

JackBol

Security is not an option!

Inderdaad, hij maakt netjes 1x de db aan, en als je em de tweede keer aanroept, is die leeg.
vreemd. Helaas heb ik hier geen testopstelling, dus ik kan het niet even voor je bij mij testen...

De actuele opbrengst van mijn Tibber Homevolt


Acties:
  • 0 Henk 'm!

  • JackBol
  • Registratie: Maart 2000
  • Niet online

JackBol

Security is not an option!

voeg eens een


$db = get_sql();

toe voor je show debug info.

misschien hangt die dan die singleton terug aan je $db
en doe eens een show debug info van $db2

De actuele opbrengst van mijn Tibber Homevolt


Acties:
  • 0 Henk 'm!

  • Matthis
  • Registratie: Juli 2004
  • Laatst online: 13-06 13:45
als je nogmaals het singleton aanroept voor de debug info van db1, wordt deze weer leeg gemaakt, maar wordt er geen nieuwe SQL aangemaakt :s

debug-info van $db2 toont netjes de ene uitgevoerde query :s

Acties:
  • 0 Henk 'm!

  • JackBol
  • Registratie: Maart 2000
  • Niet online

JackBol

Security is not an option!

Je singleton werkt niet goed, denk ik... maar waar het precies aan ligt krijg ik op dit tijdstip ook niet meer uit mijn grijze massa getovert....

een nachtje slapen helpt, zeggen ze wel eens ;)

Nog een ding, maar eens een lokale boolean var aan, initialiseer deze op false, set deze true bij het database aanmaken. Laat hier je if op checken.

edit2: of maak de var global, het kan zijn dat als de function de tweede keer aangeroepen wrdt, de instance_db zijn waarde kwijt is (ook al zou dat niet moeten kunnen)

edit3: @NMe: ja, ik dacht er net aan... tis al laat ;)

[ Voor 55% gewijzigd door JackBol op 24-10-2005 01:21 ]

De actuele opbrengst van mijn Tibber Homevolt


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Dirk-Jan, mag ik je even wijzen op het bestaan van een edit-knop? :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Bluestorm
  • Registratie: Januari 2000
  • Laatst online: 20-08-2022
Aan je output te zien is db2 gewoon vrolijk een nieuw schoon object. Zou wel eens te maken kunnnen hebben met dat PHP standaard niet met references werkt, dus dat er ergens onderweg wat gekloond wordt. Kijk hier eens naar: http://nl3.php.net/manual/en/language.references.return.php misschien heb je er wat aan.

Tenminste... dat [ denk / zie / weet ] ik... | Javascript obfuscator | foto's en video's uploaden


Acties:
  • 0 Henk 'm!

  • JackBol
  • Registratie: Maart 2000
  • Niet online

JackBol

Security is not an option!

Bluestorm schreef op maandag 24 oktober 2005 @ 01:25:
Aan je output te zien is db2 gewoon vrolijk een nieuw schoon object. Zou wel eens te maken kunnnen hebben met dat PHP standaard niet met references werkt, dus dat er ergens onderweg wat gekloond wordt. Kijk hier eens naar: http://nl3.php.net/manual/en/language.references.return.php misschien heb je er wat aan.
maar op regel 51 - 56
code:
1
2
3
4
5
6
)

get SQL aangeroepen

sql Object
(


staat geen new SQL gemaakt

dus hij maakt de 2e keer geen sql meer aan, waar laat hij die query dan?

De actuele opbrengst van mijn Tibber Homevolt


Acties:
  • 0 Henk 'm!

  • Matthis
  • Registratie: Juli 2004
  • Laatst online: 13-06 13:45
Bluestorm schreef op maandag 24 oktober 2005 @ 01:25:
Aan je output te zien is db2 gewoon vrolijk een nieuw schoon object. Zou wel eens te maken kunnnen hebben met dat PHP standaard niet met references werkt, dus dat er ergens onderweg wat gekloond wordt. Kijk hier eens naar: http://nl3.php.net/manual/en/language.references.return.php misschien heb je er wat aan.
dat is nou net het rare: het is inderdaad telkens een nieuw SQL-object, maar de
PHP:
1
2
3
 if(!isset($instance_db)) { 
[...]
}

wordt maar eenmaal aangeroepen, pffffft

Acties:
  • 0 Henk 'm!

  • Brakkie
  • Registratie: Maart 2001
  • Niet online

Brakkie

blaat

De static waarde $instance_db in je singleton functie veranderd niet wanneer je aan de slag gaat met het kopie van het object die die functie terug gegeven heeft. Dat is het hele probleem. In feite ga je weer aan de slag met een leeg object als je get_sql weer aanroept.

Of je dit probleem kan verhelpen door het object by reference terug te geven kan ik ff niet testen.

[ Voor 23% gewijzigd door Brakkie op 24-10-2005 01:38 ]

Systeem | Strava


Acties:
  • 0 Henk 'm!

  • Matthis
  • Registratie: Juli 2004
  • Laatst online: 13-06 13:45
Brakkie schreef op maandag 24 oktober 2005 @ 01:35:
De static waarde $instance_db in je singleton functie veranderd niet wanneer je aan de slag gaat met het kopie van het object die die functie terug gegeven heeft. Dat is het hele probleem. In feite ga je weer aan de slag met een leeg object.

Of je dit probleem kan verhelpen door het object by reference terug te geven kan ik ff niet testen.
wanneer ik $instance_db =& new SQL(...) of function &get_sql() of $db =& get_sql of elke mogelijke combinatie probeer, worden er duidelijk telkens nieuwe objecten gemaakt...

Acties:
  • 0 Henk 'm!

  • JackBol
  • Registratie: Maart 2000
  • Niet online

JackBol

Security is not an option!

Brakkie schreef op maandag 24 oktober 2005 @ 01:35:
De static waarde $instance_db in je singleton functie veranderd niet wanneer je aan de slag gaat met het kopie van het object die die functie terug gegeven heeft. Dat is het hele probleem. In feite ga je weer aan de slag met een leeg object als je get_sql weer aanroept.

Of je dit probleem kan verhelpen door het object by reference terug te geven kan ik ff niet testen.
dat object by reference terug geven heb je nodig voor je $db = get_sql();

maar hij checkt de $instance_db nog voordat hij het tweede object aanmaakt... dus dat zou er niets mee te maken hoeven hebben...

maar je zou het kunnen proberen om een extra lokale boolean aan te maken voor de controle of het object al een keer bestaat...

De actuele opbrengst van mijn Tibber Homevolt


Acties:
  • 0 Henk 'm!

  • Bluestorm
  • Registratie: Januari 2000
  • Laatst online: 20-08-2022
Bij mij werkt het als je function &get_sql(...) schrijft en $db = &get_sql() Tenminste in mijn simpele voorbeeldje:

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
<?php

class A{
    var $message = "";
    function log($str){
        $this->message.="\n".$str;   
    }
}

function &get_A(){
    static $instance_db; 
  
    if(!isset($instance_db)) { 
        $instance_db = new A();
        $instance_db->log('created');
    } 
    
    return $instance_db;  
    
}
echo "<pre>";
$a1 = &get_A();
$a1->log("A1");
echo $a1->message;
echo "\n";
$a2 = &get_A();
$a2->log("A2");
echo $a2->message;
echo "</pre>";

?>


die print netjes

created, A1
created, A1,A2

Tenminste... dat [ denk / zie / weet ] ik... | Javascript obfuscator | foto's en video's uploaden


Acties:
  • 0 Henk 'm!

  • Matthis
  • Registratie: Juli 2004
  • Laatst online: 13-06 13:45
THANKS

dit werkt, blijkbaar had ik deze combinatie van reference over het hoofd gezien! 8)7
manmanman, thanks, bedankt!!!

Acties:
  • 0 Henk 'm!

  • Brakkie
  • Registratie: Maart 2001
  • Niet online

Brakkie

blaat

$instance_db blijft keurig leeg omdat de er met deze static variabele helemaal niks gebeurd binnen de function scope.

Als ik deze pagina http://nl3.php.net/global moet geloven kan je ook geen reference geven naar een static variabele binnen een functie.

Systeem | Strava

Pagina: 1