PDA

Afficher la version complète : [Réglé] [Réglé][PHP] Objet singleton.



jufedo
09/09/2010, 13h32
Bonjour,

J'ai un fichier d'index qui "route" vers un des répertoires site en fonction de l'URL. Quelques extraits du fichier:


// des trucs qui n'ont rien à voir avec la question...

// define site directory with hostname

$host = $_SERVER['HTTP_HOST'];
$sitedir = $sites['default'];
if(array_key_exists($host, $sites))
$sitedir = $sites[$host];

// des trucs qui n'ont rien à voir avec la question...

// Define the absolute paths for configured directories
define('SITEPATH', realpath($applications).DIRECTORY_SEPARATOR.$sited ir.DIRECTORY_SEPARATOR);

// des trucs qui n'ont rien à voir avec la question...

// Bootstrap the application
require SITEPATH.'bootstrap.php';
linafsite::getInstance()->chargement();

// des trucs qui n'ont rien à voir avec la question...

Dans les bootstrap.php des sites, on a une seule chose: un objet singleton qui est sensé être unique. À son instanciation, il charge les paramètres de conf. La méthode chargement(), charge un objet de type page. Quelques extraits du fichier:




<?php defined('LINAF') or die('No direct script access.');

class linafsite {

protected static $_instance;

/**
* Empêche la création externe d'instances.
*/
private function __construct () {
// à la construction, on va charger la conf un fichiers JSON.
}

/**
* Empêche la copie externe de l'instance.
*/
private function __clone () {}

/**
* Renvoi de l'instance et initialisation si nécessaire.
*/
public static function getInstance () {
if (!(static::$_instance instanceof static))
static::$_instance = new static();

return static::$_instance;
}


public function chargement (){
// des trucs pas utiles ici.
return static::stick($urls);
}

/**
* stick
*
* Used to use URL to mapp object and methods.
*
* @param array $urls The regex-based url to class mapping
*
*/

public static function stick($urls) {
// méthode router une l'URL comme ça:
// http://domain/classe/objet/méthode

On a donc l'objet LINAF qui est unique. Unique?

C.A.D que s'il est appelé plusieurs fois dans l'index, il restera unique. ok
Mais si plusieurs utilisateurs accèdent au même site en lançant le index.php, cette objet ne sera t il chargé qu'une seule fois par PHP et on en aura qu'une seule version en mémoire?
Ou est-il chargé à chaque appel d'index.php et détruit à la fin de celui-ci ?


PS: LINAF signifie LINAF Is Not A Framework. Je vous reparlerais de mon projet dès qu'il sera plus avancé ;)

salv-ice
09/09/2010, 14h38
Hello,

Par définition, un objet singleton est unique à l'application entière, donc il ne sera chargé qu'une fois en mèmoire.

Amicalement.

salv-ice.

jufedo
09/09/2010, 16h58
Ok merci.

Excuses moi si je suis lourd, mais je n'ai pas une grande confiance en PHP s'agissant de son modèle de POO:
Donc, s'il y a 100 utilisateurs, l'objet ne sera instancié qu'une seule fois?
Le constructeur de l'objet fait de "gros" calculs pour établir la configuration, ces calcules ne seront donc réalisés qu'une seule fois?

Il serait donc stupide d'utiliser un système de cache?

(edit)
Peut être y a t il un problème dans cette implémentation du patern singleton mais j'ai ajouté un echo "instanciation du singleton"; au constructeur et à chaque rechargement de la page, j'ai un instanciation du singleton. Je vais finalement garder la mise en cache pour le moment.

salv-ice
09/09/2010, 17h16
En théorie, le constructeur ne sera exécuté qu'une fois. Dans la pratique, il pourrait s'exécuter plusieurs fois en fonction de la manière dont le garbage collector de php fonctionne. Je ne suis pas un expert en php... mais en Java, cela peut arriver si l'instance de l'objet devient trop "vieille".

Edit : Ou as-tu trouve cette implémentation du pattern singleton ? La fonction getInstance me parait étrange, ça ne devrait pas plutot être quelque chose comme ça (mon php est rouillé, désolé) :


public static function getInstance() {
if( ! isset(self::$_instance)) {
self::$_instance = new linafsite()
}
return self::$_instance;
}

Silfax
09/09/2010, 18h52
Salut,

Euh .. Il n'y a pas de garbage collector en PHP .. De plus à chaque requête, le "singleton" (en php) est en effet réinitialisé car il est appelé à chaque session. L'implémentation que tu donnes concerne uniquement un code php sans requête et là effectivement ça marche.... De nombreux post (en anglais) en parle. Si tu ne veux avoir qu'une seule instanciation par client, tu dois stocker l'instance de ta classe dans $_SESSION ..
Voir ICI (http://www.talkphp.com/advanced-php-programming/1304-how-use-singleton-design-pattern.html#post28065)

Sfx

salv-ice
09/09/2010, 19h31
Salut,

Euh .. Il n'y a pas de garbage collector en PHP .. De plus à chaque requête, le "singleton" (en php) est en effet réinitialisé car il est appelé à chaque session. L'implémentation que tu donnes concerne uniquement un code php sans requête et là effectivement ça marche.... De nombreux post (en anglais) en parle. Si tu ne veux avoir qu'une seule instanciation par client, tu dois stocker l'instance de ta classe dans $_SESSION ..
Voir ICI (http://www.talkphp.com/advanced-php-programming/1304-how-use-singleton-design-pattern.html#post28065)

Sfx[/b]

Bon à savoir... même si je ne fais plus de php :)

Mais il me semblait qu'un GC avait été ajouté à php récemment...

Silfax
09/09/2010, 19h34
oui à PHP >= 5.3.0 mais peu de sites sont développés dans cette version ...D'ailleurs les commandes (gc_enable, gc_desable, etc..) ne sont pas documentées ...

Sfx

jufedo
09/09/2010, 22h59
Merci à vous deux.

Stocker l'instance dans la session est en effet une bonne idée.