Classes en PHP (instance unique)

Fermé
nickleus Messages postés 374 Date d'inscription dimanche 20 janvier 2008 Statut Membre Dernière intervention 18 juin 2011 - 13 mai 2009 à 11:58
pyschopathe Messages postés 1974 Date d'inscription dimanche 2 mars 2008 Statut Membre Dernière intervention 22 mars 2010 - 18 mai 2009 à 13:09
Bonjour à tous,

j'ai lu cette article (ce tuto) : https://apprendre-php.com/tutoriels/tutoriel-45-singleton-instance-unique-d-une-classe.html

Qui explique comment créer une instance unique d'une classe. Je pense avoir saisie comment ça fonction. Mais je vois pas à quoi cela peut servir dans un cas concret.

Ou plutôt qu'est ce que cela peut apporter de créer un objet de ce type dans d'autres classes ?

Merci d'avance de votre éclaircissement.
A voir également:

22 réponses

nico7382 Messages postés 279 Date d'inscription lundi 6 juin 2005 Statut Membre Dernière intervention 22 décembre 2010 50
13 mai 2009 à 13:49
Salut,


Le lien est foureux ^^, mais bon :
https://apprendre-php.com/tutoriels/tutoriel-45-singleton-instance-unique-d-une-classe.html

je connaissais pas non plus, mais bon, ce qui est peut être intéressant dans les singletons, c'est par exemple dans le cas, où plusieurs utilisateurs font des choses en parallèle:

Paul travail sur un document, et Jacques sur un autre.
Jacques fini sont boulot sur son doc plus tôt et il veut aider Paul à finir le sien, et bah, il ne pourra pas , car paul est déjà sur le document, le singleton t'indique que le document est déjà en édition par exemple.

Voilà un exemple, dans la majorité des cas, quand c'est pas géré ainsi, Jacques accède avec l'ancienne version du doc, et s'il enregistre après que paul est enregistré, Jacques effaces les données que Paul à marqué.


Si je me trompe n'hésite pas ^^
0
nickleus Messages postés 374 Date d'inscription dimanche 20 janvier 2008 Statut Membre Dernière intervention 18 juin 2011 5
14 mai 2009 à 10:48
Merci, c'est déjà un peu plus claire

Il va falloir que j'intègre cela dans mes codes maintenant. ;)
0
nickleus Messages postés 374 Date d'inscription dimanche 20 janvier 2008 Statut Membre Dernière intervention 18 juin 2011 5
14 mai 2009 à 19:07
Bonsoir,

Encore une petite question sur ce sujet. Dans le tuto que j'ai cité plutôt, est-ce une obligation de déclarer un private la méthode __construct ( ) ?

Car je fait un extends d'une autre class, et si ma méthode __construct ( ) (de la première class) est en private, ça ne marche pas.

houa, j'éspère que c'est claire tout ce ! :-))

Merci d'avance.
0
P@t@ch0n Messages postés 565 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 28 décembre 2009 85
14 mai 2009 à 21:12
Oui, c'est nécessaire, car en appelant directement le constructeur, tu auras une autre instance de ta classe, ce qui n'a plus aucun intérêt.

L'héritage d'une classe mère dont l'instance s'effectue via un singleton n'a aucun sens.

nico7382, ton explication m'as bien fait marrer, mais c'est pas du tout ça le but.

Un exemple plus basique, et concret.
Une classe Page dans une application qui s'occupe de mettre en forme une page html, bien évidemment, on ne veut qu'une instance de cette classe, sinon, on se retrouverait, avec plusieurs « pages ».
Plusieurs autres classes feront appel au singleton de cette classe, par exemple, une classe news, une classe menu, une classe formulaire, etc..
0
nickleus Messages postés 374 Date d'inscription dimanche 20 janvier 2008 Statut Membre Dernière intervention 18 juin 2011 5
14 mai 2009 à 22:11
Ton idée est intéressante ! Qui plus est elle se rapproche de mon type de projet ;)

Ce que je ne comprends pas dans ton explication, c'est que l'osque l'on charge une page, elle dépend de l'url, alors comment elle pourrait créer plusieurs "pages" ? (En faite je n'est pas vraiment compris le sens ce bout d'explication)

Est ce que cela voudrais aussi dire, qu'il faut créer un singleton pour chacune des parties ?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
P@t@ch0n Messages postés 565 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 28 décembre 2009 85
14 mai 2009 à 23:14
J'avais mit des guillemets justement pour dire que ce n'était pas plusieurs pages au sens réel, mais plusieurs code de pages html mit bout à bout.

Il faut voir « page » comme un container global d'une page, contenant sa structuration (html).

Par exemple cette classe posséderait une méthode entete(), une méthode menu(), une méthode contenu(), une méthode corps(), etc...

Non pourquoi vouloir créer un singleton pour chaque partie ? tout dépend du but de la classe.
0
nickleus Messages postés 374 Date d'inscription dimanche 20 janvier 2008 Statut Membre Dernière intervention 18 juin 2011 5
15 mai 2009 à 09:10
Oui, c'est pas faux.

je reviens à ce que tu disais :

Oui, c'est nécessaire, car en appelant directement le constructeur, tu auras une autre instance de ta classe, ce qui n'a plus aucun intérêt.


S'il faut mettre en private le constructeur, on ne peux donc pas faire appel à une extension de class ?

Exemple


class bibi
{
code ...
}

class bobo extends bibi
{
code avec instance ...
}
0
P@t@ch0n Messages postés 565 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 28 décembre 2009 85
15 mai 2009 à 09:21
Non, on ne peut pas en mettant la visibilé du constructeur en private.

Mais comme je t'ai dis précédemment, faire une classe fille héritant d'une classe mère dont l'instance se fait par singleton n'a aucun sens.
0
nickleus Messages postés 374 Date d'inscription dimanche 20 janvier 2008 Statut Membre Dernière intervention 18 juin 2011 5
15 mai 2009 à 09:38
houa, tu es toujours sur ton PC ! lol

Je pense qu'en prenant une class que je suis entrain de créer comme exemple m'aiderai à mieux comprendre. Car je t'avoue que les class sont encore un grand mystère pour moi.

Je suis entrain de créer une class de traduction de langue :

Elle récupère le mot à traduire, puis je charge un fichier ini (suivant la page, j'en dit pas plus c'est très long à expliquer) où chaque ligne est contituée de la façon suivante :

CLE=valeur

dont je fait un explode pour avoir un tableau de type array ( [CLE] => valeur ). Puis je retourne la valeur et j'affiche.

Qu'elle serait l'intérêt de mette cette class en instance ?
0
P@t@ch0n Messages postés 565 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 28 décembre 2009 85
15 mai 2009 à 10:37
L'intérêt serait de ne charger qu'une seule fois ton fichier au cas où ton application ferait appel plusieurs fois dans divers endroit à ta classe.
0
nickleus Messages postés 374 Date d'inscription dimanche 20 janvier 2008 Statut Membre Dernière intervention 18 juin 2011 5
15 mai 2009 à 11:05
D'accord, encore une pitit question et après j'arrête de t'embêter :)

Est-ce qu'une instance d'une class peu faire office de "global" ou ça n'a rien à voir ?

Un peu comme lorsque l'on appel une variable dans une fonction.
0
pyfeu Messages postés 38 Date d'inscription vendredi 23 mai 2008 Statut Membre Dernière intervention 26 novembre 2009
15 mai 2009 à 11:12
L'intéret aussi est de ne pas créer plein d'objet à chaque fois
exemple : une première classe :
class FamilleDAO {

// Sauvegarde de l'instance
private static $_instance;
private $connexion;


/**
*
*/
private function __construct () {
global $host_db, $user_login, $user_password, $database, $acces_log;
$this->connexion = MySQLConnection::instance($acces_log);
if(!$this->connexion->isValid()){
$this->connexion->connect($host_db, $user_login, $user_password);
$this->connexion->useDB($database);
}
}

/**
*
*/
private function __clone () {}

/**
*
*/
public static final function getInstance(){
if (!isset(self::$_instance))
{
$c = __CLASS__;
self::$_instance = new $c();
}
return self::$_instance;
}

cette classe va servir par exemple a ajouter, supprimer des éléments de le base de données.
-------------------------------------------------------------------------
une classe qui va utilisé :
fera comme cela :
$familleDAO = FamilleDAO::getInstance();
et il n'y aura donc pas de nouvelle création d'objet
0
nickleus Messages postés 374 Date d'inscription dimanche 20 janvier 2008 Statut Membre Dernière intervention 18 juin 2011 5
15 mai 2009 à 11:21
Est ce que le "final" veux dire la l'objet sera "détruit" à la fin de l'exécution ?
0
pyschopathe Messages postés 1974 Date d'inscription dimanche 2 mars 2008 Statut Membre Dernière intervention 22 mars 2010 135
18 mai 2009 à 12:48
Le mot-clé final signifie que la méthode ne pourra pas être redéfinie dans le classes filles (en cas d'héritage).

edit : la prochaine fois je lirai jusqu'au bout >_<
0
pyfeu Messages postés 38 Date d'inscription vendredi 23 mai 2008 Statut Membre Dernière intervention 26 novembre 2009
15 mai 2009 à 11:29
Non ça ne le détruit pas (je ne suis pas sur à 100% car je sais plus trop ce que ça fait final :s )
Mais il me semble que ça empêche la redéfinition de la fonction .
0
P@t@ch0n Messages postés 565 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 28 décembre 2009 85
15 mai 2009 à 18:50
C'est ça, le final empêche la redéfinition de la méthode par une classe enfant.

Est-ce qu'une instance d'une class peu faire office de "global" ou ça n'a rien à voir ?

Si tu entends par là qu'une classe instanciée par singleton est une parade à la mise à global de la variable contenant l'objet, je dirais que oui.
0
nickleus Messages postés 374 Date d'inscription dimanche 20 janvier 2008 Statut Membre Dernière intervention 18 juin 2011 5
15 mai 2009 à 19:09
Donc je pourrais très bien instanciée ma classs (sinlgeton) en dehors de toutes mes classes et faire appel à une de ces méthodes dans n'importe quel autres classe ?

C'est ça ? Parce que ça m'arrangerais dans certains cas !
0
P@t@ch0n Messages postés 565 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 28 décembre 2009 85
15 mai 2009 à 20:50
Oui, mais tu es obligé de passer par le singleton de la classe pour y accéder.
0
nickleus Messages postés 374 Date d'inscription dimanche 20 janvier 2008 Statut Membre Dernière intervention 18 juin 2011 5
15 mai 2009 à 21:21
MMM J'ai essayé un truc de ce genre :

class test
{
private function __construct ( ) 
{
echo "bibi";
}

public function getInstance ( )
{
static $instance;

if ( !isset ( $instance ) )
{
$instance = new test ( );
}

return $instance;
}

}


puis :

class test2
{

public function __contruct ( )
{
$var;
} 

}

$var = test::getInstance ( );
$val = new test2 ( );


Mais bien sur ça ne marche pas puisque la variable $var n'est pas définie. Pourquoi ? puisque j'ai déclarer la variable par un singleton. Ou alors est ce que ça marche qu'a partir du moment que les classes sont "empilée" ?
0
P@t@ch0n Messages postés 565 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 28 décembre 2009 85
15 mai 2009 à 22:04
Il faut toujours accéder à ton instance dans ton singleton avec self.

Tu n'as pas bien compris le fonctionnement je pense, en mettant un echo dans le constructeur, il ne sera affiché quuu'une seule fois, peu importe le nombre d'appel au singleton.

Les variables n'ont que des portées locales dans le fonctions.

Un exemple :

class Test
{
   private $qui;
   private static $instance;
   
   private function __construct($qui) 
   {
      $this->qui = $qui;
   }

   public function getInstance($qui)
   {
      if( !isset(self::$instance) )
         self::$instance = new Test($qui);
      return self::$instance;
   }
   
   public function getQui()
   {
      return $this->qui . "\n";
   }
}

class Test2
{
   private $Test;
   
   public function __construct()
   {
      $this->Test = Test::getInstance(__CLASS__);
   }
   
   public function getQui()
   {
      return $this->Test->getQui();
   }
}

//* Dans cet ordre, affichera Externe 2 fois
$Test = Test::getInstance('Externe');
echo $Test->getQui();

$Test2 = new Test2();
echo $Test2->getQui();//*/

// À l'inverse, affichera Test2 2fois
$Test2 = new Test2();
echo $Test2->getQui();

$Test = Test::getInstance('Externe');
echo $Test->getQui();
0
nickleus Messages postés 374 Date d'inscription dimanche 20 janvier 2008 Statut Membre Dernière intervention 18 juin 2011 5
16 mai 2009 à 19:13
Oui, maintenant je comprends mieux. En faite on pourrait considéré que cette instance, pourrait être une mémoire tampon entre plusieurs classes !

Et si par exemple, j'ai une méthode qui utiliser un array_push, je pourrais ajouter autant de valeurs suivant le nombre de classes qui appel cette instance.

Est ce c'est bien ça ?
0
pyschopathe Messages postés 1974 Date d'inscription dimanche 2 mars 2008 Statut Membre Dernière intervention 22 mars 2010 135
18 mai 2009 à 13:09
Une utilisation de la classe singleton serait une classe de paramétrage : à sa construction, cette classe lit un fichier de paramètres et garde les valeurs en mémoire. Lorsqu'elle est détruite, si des paramètres ont été modifiés, elle réécrit le fichier de paramètres.

Tous les objets de ton application partagent les mêmes paramètres, donc si l'objet A modifie le paramètre 'toto', il faut que si l'objet B demande la valeur du parmètre 'toto', il obtienne la valeur modifiée. La classe Parametre devrait donc être un singleton, c'est à dire qu'il n'existera toujours qu'une seule instance (ou zéro si pas encore construit).

Les buts principaux sont le partage de données et l'économie de ressources. Dans le cas du fichier de paramètres, le partage est évident, et le fait de n'utiliser qu'une instance économise les accès au système de fichier et le parsing du fichier de paramètres.

Je n'ai pas compris ta question sur array_push...
0
P@t@ch0n Messages postés 565 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 28 décembre 2009 85
17 mai 2009 à 17:25
Et si par exemple, j'ai une méthode qui utiliser un array_push, je pourrais ajouter autant de valeurs suivant le nombre de classes qui appel cette instance.

Je n'ai pas bien compris ce que tu dis.
0