Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

probleme de singleton en php

25 réponses
Avatar
ownowl
bonjour à tous

je souhaite faire un singleton en php (c'est à dire qu'il n'y ai qu'une
seule instance d'une classe dans l'environnement php)

Le problème est : A chaque fois que je fais appel à
TypesTruc::getInstance()->getTypes()
je repasse systématiquement dans le constructeur.


class TypesTruc {

private static $instance;

private $types = array();

private function __construct() {
$this->types['0'] = 'truc1;
$this->types['1'] = 'truc2';
}

final public static function getInstance() {
if (!IsSet(self::$instance)) {
error_log('initialisation du singleton');
self::$instance = new TypesTruc ();
}
return self::$instance;
}

public function getTypes(){
return $this->types;
}
}


une idée ?
Olivier

10 réponses

1 2 3
Avatar
Thierry
"ownowl" a écrit dans le message de
news:4614a3cd$0$21147$
bonjour à tous
bonjour



je souhaite faire un singleton en php (c'est à dire qu'il n'y ai qu'une
seule instance d'une classe dans l'environnement php)
ok



Le problème est : A chaque fois que je fais appel à
TypesTruc::getInstance()->getTypes()
je repasse systématiquement dans le constructeur.
tu veux dire à chaque appel de la page ?


essaie ton code modifié suivant:

<?php
class TypesTruc {
private static $instance;
private $types = array();

private function __construct() {
echo "contruction <br />";
$this->types['0'] = 'truc1;
$this->types['1'] = 'truc2';
}

final public static function getInstance() {
if (!IsSet(self::$instance)) {
error_log('initialisation du singleton');
self::$instance = new TypesTruc ();
}
return self::$instance;
}

public function getTypes(){
return $this->types;
}
}

print_r(TypesTruc::getInstance()->getTypes());
echo "<hr />";
print_r(TypesTruc::getInstance()->getTypes());

?>

tu devrais constater que le constructeur n'est appelé qu'une fois dans la
page.
mais à chaque appel de le page il va être rappelé.

thierry

Avatar
Thomas Labourdette
Bonjour,

ownowl a écrit le jeudi 5 avril 2007 09:41 :


je souhaite faire un singleton en php (c'est à dire qu'il n'y ai qu'une
seule instance d'une classe dans l'environnement php)

Le problème est : A chaque fois que je fais appel à
TypesTruc::getInstance()->getTypes()
je repasse systématiquement dans le constructeur.


Je viens de faire le test en PHP 5 et je n'ai pas ton problème.

@+
--
Côme LAIZOTRE (signature et citation aléatoires)
Qu'est-ce que les femmes ont tous les mois et qui dure 3 ou 4 jours ?
Le salaire de leur mari...

Avatar
ownowl
Bonjour,

ownowl a écrit le jeudi 5 avril 2007 09:41 :


je souhaite faire un singleton en php (c'est à dire qu'il n'y ai qu'une
seule instance d'une classe dans l'environnement php)

Le problème est : A chaque fois que je fais appel à
TypesTruc::getInstance()->getTypes()
je repasse systématiquement dans le constructeur.



Je viens de faire le test en PHP 5 et je n'ai pas ton problème.

@+


merci de ta réponse

Tu veux dire que dans ton log, tu n'as qu'une seule ligne de
'initialisation du singleton' quelque soit le nombre de page appelée ?
Olivier


Avatar
Olivier Miakinen

Le problème est : A chaque fois que je fais appel à
TypesTruc::getInstance()->getTypes()
je repasse systématiquement dans le constructeur.


Je viens de faire le test en PHP 5 et je n'ai pas ton problème.


Tu veux dire que dans ton log, tu n'as qu'une seule ligne de
'initialisation du singleton' quelque soit le nombre de page appelée ?


Ah non, ça ce n'est pas possible. Lorsque le script PHP s'arrête, toute
la mémoire allouée est libérée... ce d'autant plus lorsque PHP est lancé
sous forme de CGI plutôt que de module Apache, puisque alors c'est
carrément le process qui s'arrête.

Si tu veux de la persistance de données entre deux appels de scripts, tu
dois utiliser un fichier ou une base de données.



Avatar
ownowl
merci de ta réponse


tu devrais constater que le constructeur n'est appelé qu'une fois dans la
page.


ok

mais à chaque appel de le page il va être rappelé.



oui je suis d'accord, mais c'est bien ca que je veux éviter. Je cherche
que le constructeur soit appelé une seule fois, à la première
utilisation de TypesTruc::getInstance(), quelque soit le nombre de pages
appelées ensuite.
Je précise que je viens du monde java, et qu'en java le constructeur
d'un singleton n'est appelé un seule fois durant la durée de vie de la
machine virtuelle. Cela est-il possible en php (sans utiliser un système
de cache (et d'ailleur un cache, pour être efficace doit bien rester en
mémoire en les appel des différentes pages))?

Olivier

Avatar
Olivier Miakinen

oui je suis d'accord, mais c'est bien ca que je veux éviter. Je cherche
que le constructeur soit appelé une seule fois, à la première
utilisation de TypesTruc::getInstance(), [quel que] soit le nombre de pages
appelées ensuite.


Voyons les implications d'un tel mécanisme. L'objet serait créé une
fois sur le serveur, et ne serait jamais détruit jusqu'au reboot de
celui-ci. Tous les utilisateurs de ton script utiliseraient donc le
même (forcément, puisque le serveur ne peut pas distinguer entre deux
requêtes HTTP pour savoir laquelle vient de la même « session d'un
navigateur », laquelle vient d'une autre session, laquelle vient d'un
autre ordinateur, etc.).

Par suite, les objets non réutilisés consommeraient de la place mémoire
jamais libérée (à moins d'arrêter et relancer le serveur), et tu ne
pourrais jamais modifier un script contenant un tel objet sans arrêter
le serveur, puisque des utilisateurs pourraient toujours avoir besoin
de l'ancienne version.

Pas top, à mon avis.

Je précise que je viens du monde java, et qu'en java le constructeur
d'un singleton n'est appelé un seule fois durant la durée de vie de la
machine virtuelle.


Ne me dis pas que la machine virtuelle se trouve sur le serveur, et
qu'une seule et unique machine virtuelle est utilisée par tous les
visiteurs d'un site : je ne te croirais pas.

Et même si tu parlais d'une machine virtuelle tournant sur l'ordinateur
du visiteur, est-ce qu'elle conserve les objets quand tu quittes une
page d'un site pour en ouvrir une autre ? Parce que c'est bien ça qui
se passe avec PHP. Voir <http://faqfclphp.free.fr/#rub2.3>.

Cela est-il possible en php (sans utiliser un système
de cache (et d'ailleur un cache, pour être efficace doit bien rester en
mémoire en les appel des différentes pages))?


Quelle mémoire ?

Avatar
ownowl
Voyons les implications d'un tel mécanisme. L'objet serait créé une
fois sur le serveur, et ne serait jamais détruit jusqu'au reboot de
celui-ci. Tous les utilisateurs de ton script utiliseraient donc le
même (forcément, puisque le serveur ne peut pas distinguer entre deux
requêtes HTTP pour savoir laquelle vient de la même « session d'un
navigateur », laquelle vient d'une autre session, laquelle vient d'un
autre ordinateur, etc.).

Par suite, les objets non réutilisés consommeraient de la place mémoire
jamais libérée (à moins d'arrêter et relancer le serveur), et tu ne
pourrais jamais modifier un script contenant un tel objet sans arrêter
le serveur, puisque des utilisateurs pourraient toujours avoir besoin
de l'ancienne version.

Pas top, à mon avis.


c'est pourtant le but de ce design pattern. La gestion d'un
service/objet commun à l'ensemble des requêtes utilisateur.



Je précise que je viens du monde java, et qu'en java le constructeur
d'un singleton n'est appelé un seule fois durant la durée de vie de la
machine virtuelle.



Ne me dis pas que la machine virtuelle se trouve sur le serveur, et
qu'une seule et unique machine virtuelle est utilisée par tous les
visiteurs d'un site : je ne te croirais pas.


et pourtant, généralement c'est bien comme ca que ca se passe ! Les
serveur d'apllication java du type weblogic, websphere, tomcat,...,
fonctionnent au sein d'une seule machine virtuelle, (même s'il est
possible d'en avoir plusieurs) et toutes les requêtes utilisateurs
tourne dans cette VM.


Et même si tu parlais d'une machine virtuelle tournant sur l'ordinateur
du visiteur, est-ce qu'elle conserve les objets quand tu quittes une
page d'un site pour en ouvrir une autre ? Parce que c'est bien ça qui
se passe avec PHP. Voir <http://faqfclphp.free.fr/#rub2.3>.


Cela est-il possible en php (sans utiliser un système
de cache (et d'ailleur un cache, pour être efficace doit bien rester en
mémoire en les appel des différentes pages))?



Quelle mémoire ?


j'ai vu, sans toutefois creuser, qu'il y avait des bibliotèques ou
framework php qui proposent une gestion de cache. L'intérêt d'un cache,
c'est justement de garder un mémoire (sur le serveur) des informations
souvent sollicitées. Un accès mémoire sera toujours beaucoup plus rapide
qu'un accès fichier ou base de données


Avatar
slambert
oui je suis d'accord, mais c'est bien ca que je veux éviter. Je cherche
que le constructeur soit appelé une seule fois, à la première utilisation
de TypesTruc::getInstance(), quelque soit le nombre de pages appelées
ensuite.
Je précise que je viens du monde java, et qu'en java le constructeur d'un
singleton n'est appelé un seule fois durant la durée de vie de la machine
virtuelle. Cela est-il possible en php (sans utiliser un système de cache
(et d'ailleur un cache, pour être efficace doit bien rester en mémoire en
les appel des différentes pages))?


PHP n'est pas un serveur d'application.

Il n'y a pas d'espace mémoire commun à l'application.

Tout appel de page lance un process mémoire distinct dans lequel s'execute
le script, espace mémoire qui est ensuite purgé.

Il ne vous sera pas possible d'initailiser une statique et de chercher à
jouer avec sa valeurs depuis des appels de page distincts.

@++

Stef

Avatar
LEMAIRE Mathieu
Le problème est : A chaque fois que je fais appel à
TypesTruc::getInstance()->getTypes()
je repasse systématiquement dans le constructeur.
Je viens de faire le test en PHP 5 et je n'ai pas ton problème.

Tu veux dire que dans ton log, tu n'as qu'une seule ligne de

'initialisation du singleton' quelque soit le nombre de page appelée ?


Ah non, ça ce n'est pas possible. Lorsque le script PHP s'arrête, toute
la mémoire allouée est libérée... ce d'autant plus lorsque PHP est lancé
sous forme de CGI plutôt que de module Apache, puisque alors c'est
carrément le process qui s'arrête.


Ben les sessions en PHP elles sont gérées comment alors ???
Les singletons liés à une session pourraient être stockés dans $_SESSION
non ?

par contre ces variables ne seront pas dispo à vie comme sur ton serveur
d'app..

tiens, j'ai trouvé ça :
http://linuxfr.org/forums/21/8544.html

Si tu veux de la persistance de données entre deux appels de scripts, tu
dois utiliser un fichier ou une base de données.



++

--
{Maz}




Avatar
Olivier Miakinen

Ne me dis pas que la machine virtuelle se trouve sur le serveur, et
qu'une seule et unique machine virtuelle est utilisée par tous les
visiteurs d'un site : je ne te croirais pas.


et pourtant, généralement c'est bien comme ca que ca se passe ! Les
serveur d'apllication java du type weblogic, websphere, tomcat,...,
fonctionnent au sein d'une seule machine virtuelle, (même s'il est
possible d'en avoir plusieurs) et toutes les requêtes utilisateurs
tourne dans cette VM.


Ça me semble une problématique différente. Tu peux très bien avoir
un serveur applicatif écrit en PHP, mais dans ce cas il tournera
indépendamment du serveur web « standard », même si ce serveur web
peut très bien servir à lancer des scripts PHP qui communiqueront
avec le serveur applicatif.

Quelle mémoire ?


j'ai vu, sans toutefois creuser, qu'il y avait des bibliotèques ou
framework php qui proposent une gestion de cache.


Il serait intéressant que tu creuses. Parce que à côté du temps passé à
transmettre la requête HTTP (quelques centaines de seconde si tout va
bien, plusieurs secondes en RTC), du temps passé à lancer l'interpréteur
PHP s'il n'est pas en module Apache, du temps passé à lire et exécuter
le script PHP, et du temps passé à renvoyer la réponse HTTP (incluant
une page HTML complète depuis le DOCTYPE jusqu'à la balise </html>), je
ne suis pas sûr que le temps gagné à lire une mémoire partagée plutôt
que de chercher une info en base de données soit si important que ça.

D'autant plus que si les données changent il faudra bien les écrire sur
le disque quand même pour ne pas tout perdre en cas d'arrêt inopiné du
serveur.

L'intérêt d'un cache,
c'est justement de garder un mémoire (sur le serveur) des informations
souvent sollicitées. Un accès mémoire sera toujours beaucoup plus rapide
qu'un accès fichier ou base de données


Il reste à savoir si l'accès au fichier n'est pas négligeable par
rapport au temps passé sur le réseau.


1 2 3