Création
d'entreprise
Posez votre question Signaler

Classes en PHP (instance unique)

nickleus 378Messages postés 20 janvier 2008Date d'inscription 18 juin 2011Dernière intervention - Dernière réponse le 18 mai 2009 à 13:09
Bonjour à tous,
j'ai lu cette article (ce tuto) : http://www.apprendre-php.com/...
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.
Lire la suite 

Classes en PHP (instance unique) »

Suggestions
25 réponses
Réponse
+0
moins plus
Salut,


Le lien est foureux ^^, mais bon :
http://www.apprendre-php.com/...

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 ^^
nickleus- 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. ;)
Ajouter un commentaire
Réponse
+0
moins plus
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.
Ajouter un commentaire
Réponse
+0
moins plus
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..
Ajouter un commentaire
Réponse
+0
moins plus
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 ?
Ajouter un commentaire
Réponse
+0
moins plus
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.
Ajouter un commentaire
Réponse
+0
moins plus
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 ...
}
Ajouter un commentaire
Réponse
+0
moins plus
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.
Ajouter un commentaire
Réponse
+0
moins plus
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 ?
Ajouter un commentaire
Réponse
+0
moins plus
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.
Ajouter un commentaire
Réponse
+0
moins plus
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.
Ajouter un commentaire
Réponse
+0
moins plus
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
Ajouter un commentaire
Réponse
+0
moins plus
Est ce que le "final" veux dire la l'objet sera "détruit" à la fin de l'exécution ?
pyschopathe- 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 >_<
Ajouter un commentaire
Réponse
+0
moins plus
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 .
Ajouter un commentaire
Réponse
+0
moins plus
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.
Ajouter un commentaire
Réponse
+0
moins plus
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 !
Ajouter un commentaire
Réponse
+0
moins plus
Oui, mais tu es obligé de passer par le singleton de la classe pour y accéder.
Ajouter un commentaire
Réponse
+0
moins plus
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" ?
Ajouter un commentaire
Réponse
+0
moins plus
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();
Ajouter un commentaire
Réponse
+0
moins plus
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 ?
pyschopathe- 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...
Ajouter un commentaire
Réponse
+0
moins plus
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.
Ajouter un commentaire
Ce document intitulé « Classes en PHP (instance unique) » issu de CommentCaMarche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Dossier à la une
Passage au tout numérique : quel coût pour les particuliers ?
Classes en PHP (instance unique) - page 2