Question

J'ai une situation où je pense que je pourrais avoir besoin de l'héritage dynamique des cours dans PHP 5.3, mais l'idée ne va pas bien et je cherche un modèle de conception différent pour résoudre mon problème si c'est possible.

Cas d'utilisation

J'ai un ensemble de classes de couche d'abstraction DB qui compile dynamiquement les requêtes SQL, avec une classe DAL pour chaque type de base de données (MySQL, MSSQL, Oracle, etc.). Chaque tableau de la base de données a sa propre classe qui étend la classe DAL appropriée. L'idée est que vous interagissez avec les classes de table, mais n'utilisez jamais directement la classe DAL. Si vous souhaitez prendre en charge un type de base de données différent pour votre application, vous n'avez pas besoin de réécrire aucune question ou même de code, vous modifiez simplement un paramètre qui échange une classe DAL pour un autre ... et c'est tout.

Pour vous donner une meilleure idée de la façon dont cela est utilisé, vous pouvez jeter un œil à la classe DAL, aux classes de table, et comment elles sont utilisées sur ce stackexchange Page de révision du code. Pour vraiment comprendre ce que j'essaie de faire, veuillez consulter ma mise en œuvre avant de suggérer une solution.

Problèmes

La stratégie que j'avais utilisée auparavant était de voir toutes les classes DAL partagent le même nom de classe. Cela a éliminé la mise en œuvre automatique, j'ai donc dû charger manuellement la classe DAL appropriée dans une instruction Switch. Cependant, cette approche présente certains problèmes à des fins de test et de documentation, j'aimerais donc trouver un moyen différent de résoudre le problème du chargement de la bonne classe DAL de manière plus élégante.

Mise à jour pour clarifier le problème

Le problème se résume essentiellement aux incohérences du nom de classe (pré-php 5.3) ou de l'espace de noms de classe (PHP 5.3) et de son emplacement dans la structure du répertoire. À ce stade, toutes mes classes DAL ont le même nom, DBObject, mais résident dans différents dossiers, MySQL, Oracle, etc. Mes classes de table étendent toutes DBObject, mais quel dbObject qu'ils étendent varie en fonction de celui qui a été chargé.

Fondamentalement, j'essaie d'avoir mon gâteau et de le manger aussi. Les classes de table agissent comme une API stable et étendent un backend dynamique, les classes DAL (DBObject). Cela fonctionne très bien, mais je me suis déjoué et en raison des incohérences avec les noms de classe et leurs emplacements, je ne peux pas automatiquement sur le DBObject, ce qui rend les tests unitaires en cours d'exécution et générant des documents API impossibles pour les classes DBObject parce que les tests et les documents reposent sur chargement automatique.

Le simple fait de charger le DBObject approprié en mémoire à l'aide d'une méthode d'usine ne fonctionnera pas car il y aura des moments où j'ai besoin de charger plusieurs DBObjects pour les tests. Étant donné que les classes partagent actuellement un nom, cela provoque une erreur déjà définie. Je peux faire des exceptions pour les dbObjects dans mon code de test, évidemment, mais je cherche quelque chose d'un peu moins hacky car il pourrait être futur cas où quelque chose de similaire devrait être fait.

Solutions?

Pire des cas, je peux continuer ma stratégie actuelle, mais je ne l'aime pas beaucoup, d'autant plus que je converterai bientôt mon code en PHP 5.3.

Je soupçonne que je peux utiliser une sorte d'héritage dynamique via soit des espaces de noms (préférés) ou une extension de classe dynamique, mais je n'ai pas pu trouver de bons exemples de cette implémentation dans la nature.

Dans vos réponses, veuillez suggérer soit un autre modèle qui fonctionnerait pour ce cas d'utilisation ou un exemple d'héritage dynamique bien fait. Veuillez supposer PHP 5.3 avec du code dans le name. Tous les exemples de code sont grandement encouragés et je suis définitivement ouvert à différentes approches.

Les contraintes préférées pour la solution sont:

  • La classe DAL peut être automatiquement.
  • Les classes DAL ne partagent pas exactement le même espace de noms, mais partagent le même nom de classe. Par exemple, je préférerais utiliser des classes nommées dbObject qui utilisent des espaces de noms comme Vm\Db\MySql et Vm\Db\Oracle.
  • Les classes de table ne doivent pas être réécrites avec un changement de type DB.
  • Le type de base de données approprié est déterminé via un seul paramètre. Ce paramètre est la seule chose qui devrait avoir besoin de changer pour échanger des types de base de données. Idéalement, la vérification du réglage ne devrait se produire qu'une seule fois par charge de page, mais je suis flexible à ce sujet.

Mise à jour finale

Grâce à la suggestion de Nikic, j'ai créé une classe d'usine abstraite qui charge le bon dbObject, puis enveloppe ses méthodes publiques sur une base 1: 1. Les classes de table étendent désormais l'usine au lieu de la classe DBObject.

Cette configuration me permettra désormais de tester et d'utiliser chaque classe DBObject sans me soucier des conflits et me permet d'utiliser plusieurs SGBD à la fois. Cela me permet également de conserver le code faisant allusion dans un IDE pour chaque classe de table car ils étendent chacun l'emballage d'usine. L'utilisation de méthodes d'emballage n'est peut-être pas la solution parfaite, mais elle ne s'appuie pas sur l'héritage dynamique de la classe, il résout mon problème de conception, il répond à mes exigences et cela fonctionne.

Pas de solution correcte

Licencié sous: CC-BY-SA avec attribution
scroll top