8
votes

Utilisation d'une classe de base de données Singleton dans les fonctions et plusieurs scripts (PHP) - Meilleures méthodes d'utilisation

J'ai une connexion Singleton DB que je reçois avec:

$ dbconnect = mydatabase :: getinstance ();

C'est-ce qui est assez facile. Ma question est celle qui est la méthode la moins rhétorique et la moins légitime d'utiliser cette connexion dans les fonctions et les classes? Il semble stupide de devoir déclarer la variable globale, le transmettre dans chaque fonction et / ou recréer cette variable dans chaque fonction. Y a-t-il une autre réponse pour cela?

Évidemment, je suis un noob et je peux travailler sur ce problème 10 manières différentes, dont aucune n'est vraiment attrayante pour moi. Il serait beaucoup plus facile si je pouvais avoir cette variable de DBConnect $ accessible dans n'importe quelle fonction sans avoir besoin de le déclarer global ou que je sais que je peux ajouter la variable au tableau $ _Server ... Y a-t-il quelque chose de mal avec Ce faisant? Cela me semble quelque peu inapproprié pour moi.

Une autre question rapide: est-ce une mauvaise pratique de faire cela:

$ Résultat = myDatabase :: geInstance () -> Query ($ requis);

de directement dans une fonction?


3 commentaires

Vous avez répondu à votre propre question, votre exemple d'utilisation est exactement comment vous le feriez.


Si vous envisagez de créer des classes / fonctions, qui pourraient être utilisées avec plusieurs bases de données simultanément (par exemple, travailler avec plus de bases de données simultanément) - il est préférable de passer toujours $ dbconnect à chaque classe / fonction comme paramètre, mais si vous êtes sûr que vous n'utilisez que vous n'utiliserez que simple dB toujours - alors vous pourriez simplement myDatabase :: geInstance () dans chaque classe / fonction quand vous en avez besoin.


Si vous modifiez GETInstance () pour prendre un paramètre spécifiant quelle connexion vous souhaitez (avec une valeur par défaut appropriée), vous pouvez également vous contenter de multiples problèmes de base de données (tant que la fonction sait quelle base de données il doit parler).


4 Réponses :


0
votes

J'utilise la variable superglobale $ globales pour contenir ma connexion de base de données. Works Wonders.

a tous les avantages que vous mentionnez et il n'y a absolument rien de mal ni inapproprié à ce sujet tant que vous êtes raisonnable et utilisez une clé unique pour la matrice hachage et une seule fonction d'entrée permettant de configurer la connexion de la base de données et de la stocker dans le Array.

Je vais mettre mes bouchons d'oreille maintenant, prêts pour tous les gémissements de l'utilisation de variables globales!

@downvoteurs - une lecture du coucher:

sont des variables globales mauvaises?

https://stackoverflow.com/questions/357187/global-variables-Lorsque -à-ce qu'ils sont acceptables

Certaines citations pour votre amusement:

" les variables globales sont utilisées tout le temps, par de nombreux programmeurs. Nous venons de les appeler des singletons maintenant. " - Dannysmurf

" ils sont totalement, fondamentalement, absolument, incroyablement, stupéfiez, étonnamment mauvais. " - Vinko Vrsalovic "

Et la meilleure réponse ici de Cletus lui-même: Les variables mondiales dans PHP considérées comme mauvaises pratiques? Si oui, pourquoi?


8 commentaires

Je suis assez nouveau à PHP, donc je ne peux pas commenter, mais je suis impatient d'entendre ce que les autres pourraient penser à cette idée. Merci pour la tuyauterie dans.


Malheureusement, les globals sont considérés comme une mauvaise chose et une mauvaise pratique, de manière plus sûre, propre et meilleure des moyens de résoudre ce problème, Singleton est parmi eux.


Si vous enregistrez votre objet db dans $ global (laissez-vous le sauvegarder dans $ globals ['dB'] ), il y a un risque que vous puissiez toujours le détruire avec Simple: $ globals ['db'] = null; ou nonset ($ globals ['db']); et ensuite vous n'avez aucune connexion dB ... Où utilise mydatabase :: getinstance () fait plus de sécurité que c'est toujours là


@Chrisramakers voient mon commentaire à votre réponse. Il demande autre chose.


@Laimoncijus true. Mais j'ai dit être sensible :)


@Loimoncijus, merci pour votre contribution. Ce que tu as dit a beaucoup de sens.


L'utilisation de variables globales conduit à un code désordonné. Cela peut ne pas être évident dans de petites applications comme un blog ou un forum simple, mais cela vous hantera dans de grands projets. N'utilisez tout simplement pas de globaux. Il n'y a littéralement aucune situation dans laquelle les variables mondiales sont nécessaires dans PHP5.


@Techpriester L'OP a une situation et la seule solution est celle que j'ai donnée. L'utilisation des globaux $ n'est pas exactement comme à l'aide de variables globales. Ce n'est pas comme "Global $ myvar". Et votre déclaration sur "Aucune situation où des variables globales sont nécessaires" - alors quels sont $ _BET, $ _Post, $ _Server, etc.?



0
votes

Il n'y a rien de mal à l'utilisation du singleton dans votre application, il existe des personnes contre le schéma Singleton pour les classes d'abastraction de base de données, car elles pourraient s'avérer difficiles à utiliser avec plusieurs connexions. Mais dans ce cas, le Le régime modèle, qui montre plusieurs similitudes à Singleton doit également fonctionner.

Je dirais que vous êtes sur la bonne voie!


3 commentaires

Ce n'était pas sa question. Il ne dit pas s'il devrait utiliser des singletons (il est), il veut savoir comment transmettre la référence à cet objet autour de son code.


@ZAF, merci de clarifier. @chris, c'est correct ... j'essaie de comprendre quel est le moyen le plus paresseux, le plus sûr et le moins répétitif de gérer la transmission de cette connexion DB. Je sais que je pourrais l'instancier au bas du fichier de la classe DB et l'injecter dans mes autres classes. Je me demandais simplement s'il y a une autre façon qui n'est pas aussi fronçée que les globaux de faire la même chose. Merci pour l'entrée.


Eh bien, si vous voulez rester à l'écart des globaux (que je ne peux pas vous blâmer pour) et que vous souhaitez toujours que des instances de classe soient disponibles tout au long de votre application, vous voudrez peut-être consulter le modèle de registre.



0
votes

Je l'ai traitée beaucoup au fil des ans. Je dirais que l'ajout d'un objet dérivé singleton à une variable superglobale comme $ _global ou $ _Server élimine beaucoup de point de construire une classe Singleton en premier lieu.

La meilleure pratique que je vois que c'est d'accéder à C'est comme vous le suggérez: xxx

La seule chose que j'ajouterais est que dans le cas d'une portée locale (comme une fonction ou une méthode) où vous souhaitez utiliser le singleton Objet plusieurs fois, cela pourrait valoir la peine de faire quelque chose comme: xxx


3 commentaires

Pourquoi recommanderiez-vous de ré-instantanéer la connexion par opposition à l'utilisation d'une personne déjà disponible, telles que la requête de $> DB-> si vous avez instancié l'objet dans le constructeur de classe. Y a-t-il un problème de vitesse?


Les classes Singleton ne ré-instancient pas l'objet lorsque la méthode Singleton est appelée. La méthode singleton renvoie toujours le même objet (par opposition à un nouvel objet de la même classe). en.wikipedia.org/wiki/singleton_pattern Donc, par exemple, classe myClass {Fonction singleton () {static $ cached_object = null; Si (is_null ($ cached_object)) {$ Cached_Object = nouvelle myClass (); } retour $ $ Cached_Object; }} Alors: $ objet = myClass :: singleton (); // fait et retourne un nouvel objet $ objet = myClass :: singleton (); // retourne le même objet mis en cache


Ungh, désolé pour le manque de rendements de la voiture. Vous devriez être capable de le créer ensemble.



1
votes

Une partie de cela va descendre au goût. Au travail, nous obtenons également une poignée de connexion Adodb via xxx

de même que vous pouvez raccourcir certains de ce code en utilisant la chaîne de méthode: xxx

Un registre signifie que votre code d'appel a une dépendance concrète dans votre catégorie de registre . Cela fait tester votre code difficile (personnellement, c'est la seule fois où j'ai frappé ma tête sur le mur à l'aide d'un registre) .

si vous voulez Ajouter des tests de l'unité pour votre code, vous souhaitez souvent vous moquer de votre connexion de base de données afin que vous ne manipulez pas la base de données Chaque fois que vous exécutez votre suite de tests.

Vous pouvez toujours l'obtenir en examinant votre environnement d'exécution et en configurant votre registre avec une classe d'abstraction de base de données simtueuse, mais ce n'est pas aussi élégant que l'injection de dépendance (DI).

La meilleure explication de DI et de conteneurs (pour un développeur PHP) que j'ai vu sont Injection de la dépendance de Fabien Potencier avec PHP 5.3 (à partir de la diapositive 9).

Vous passez un conteneur DI à la place d'un registre, il fournit une élégante et facile. façon d'obtenir des poignées aux dépendances (comme le registre) mais est flexible et plus lâchement couplé afin que vous puissiez se moquer de ces dépendances en cas de besoin.


0 commentaires