Classes en PHP (instance unique)
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.
--
Il n'y a pas de problèmes, il n'y a que des solutions
Configuration: vista Firefox
22 réponses
Le fil porte sur le singleton, un motif garantissant qu'une classe n'a qu'une seule instance et qu'elle soit accessible via une méthode statique comme getInstance. Plusieurs contributions montrent des usages concrets, notamment une DAO qui partage une connexion via une instance unique et via getInstance, afin d'éviter la création répétée d'objets et de ressources. D'autres échanges évoquent l'accès global maîtrisé et le rôle privé du constructeur, indiquant que le singleton peut éviter le chargement répété de fichiers lorsque la même classe est appelée à plusieurs endroits. Enfin, plusieurs participants signalent que l'intérêt du singleton dépend du contexte et que son recours peut compliquer les tests ou introduire des dépendances globales.
-
Oui, c'est possible, mais pas vraiment besoin d'objet pour faire ça, une simple fonction avec une varaible en static suffit, tout dépend de ce que souhaites faire en fait.
Une chose est certaine, c'est que les variables globaes doivent-être bannies d'une bonne application. -
A plusieurs endroit de mon script, je doit ajouter des éléments à un tableau pour l'afficher en tout dernier.
Je peux utiliser cette instance pour récupérer mes valeurs au fur et a mesure que le script avance (qui utilise plusieurs classes différentes). Puis dans un dernier script, demander à cette instance unique de m'afficher tout ce qui se trouve dans ce tableau.
Un peu comme une superglobal.
J'ai bien compris ?
PS: j'espère être plus claire ;) -
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. -
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 ?-
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...
-
-
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(); -
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" ? -
Oui, mais tu es obligé de passer par le singleton de la classe pour y accéder.
-
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 ! -
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. -
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 . -
Est ce que le "final" veux dire la l'objet sera "détruit" à la fin de l'exécution ?
-
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 -
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. -
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.
-
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 ? -
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. -
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 ?
Exempleclass bibi { code ... } class bobo extends bibi { code avec instance ... } -
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. -
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 ? -
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..
- 1
- 2