Domanda

Ho una situazione in cui penso che potrei aver bisogno dell'eredità di classe dinamica in PHP 5.3, ma l'idea non va bene e sto cercando un modello di design diverso per risolvere il mio problema se è possibile.

Caso d'uso

Ho un set di classi di strati di astrazione DB che compila dinamicamente query SQL, con una classe DAL per ogni tipo DB (MySQL, MSSQL, Oracle, ecc.). Ogni tabella nel database ha una propria classe che estende la classe DAL appropriata. L'idea è che interagisci con le classi di tabelle, ma non usi mai direttamente la classe DAL. Se si desidera supportare un tipo DB diverso per la tua app, non è necessario riscrivere alcuna domanda o anche alcun codice, modifichi semplicemente un'impostazione che scambia una classe Dal per un'altra ... e basta.

Per darti un'idea migliore di come viene utilizzato, puoi dare un'occhiata alla classe Dal, alle classi di tabelle e a come vengono utilizzate su questo stackexchange Pagina di revisione del codice. Per capire davvero cosa sto cercando di fare, dai un'occhiata alla mia implementazione prima di suggerire una soluzione.

Questioni

La strategia che avevo usato in precedenza era che tutte le classi Dal condividessero lo stesso nome di classe. Questo ha eliminato il caricamento automatico, quindi ho dovuto caricare manualmente la classe DAL appropriata in un'istruzione Switch. Tuttavia, questo approccio presenta alcuni problemi per scopi di test e documentazione, quindi vorrei trovare un modo diverso per risolvere il problema del caricamento della classe Dal corretta in modo più elegante.

Aggiornamento per chiarire il problema

Il problema sostanzialmente si riduce a incoerenze nel nome della classe (pre-PHP 5.3) o nello spazio dei nomi di classe (PHP 5.3) e nella sua posizione nella struttura della directory. A questo punto, tutte le mie classi Dal hanno lo stesso nome, dBobject, ma risiedono in diverse cartelle, MySQL, Oracle, ecc. Le mie classi di tabelle estendono tutte dBobject, ma quale dBobject si estende varia a seconda di quale è stato caricato.

Fondamentalmente, sto cercando di avere la mia torta e mangiarla anche io. Le classi di tabelle fungono da API stabile ed estendono un backend dinamico, le classi Dal (DBObject). Funziona alla grande, ma mi sono superato in astuzia e per le incoerenze con i nomi delle classi e le loro posizioni, non riesco a caricare automaticamente il DBObject, il che rende impossibili i test dell'unità in esecuzione e la generazione di documenti API per le classi DBObject perché i test e i documenti si basano su Caricamento automatico.

Basta caricare il DBObject appropriato in memoria usando un metodo di fabbrica non funzionerà perché ci saranno momenti in cui dovrò caricare più dBobject per il test. Poiché le classi attualmente condividono un nome, questo causa una classe è già definito un errore. Posso fare eccezioni per i DBObjects nel mio codice di test, ovviamente, ma sto cercando qualcosa di un po 'meno hacky in quanto potrebbero esserci casi futuri in cui dovrebbe essere fatto qualcosa di simile.

Soluzioni?

Lo scenario peggiore, posso continuare la mia strategia attuale, ma non mi piace molto, soprattutto perché presto converterò il mio codice in PHP 5.3.

Sospetto di poter usare una sorta di eredità dinamica tramite spazi dei nomi (preferiti) o un'estensione dinamica di classe, ma non sono stato in grado di trovare buoni esempi di questo implementato in natura.

Nelle risposte, suggerisci un modello alternativo che funzionerebbe per questo caso d'uso o un esempio di eredità dinamica fatta bene. Si prega di supporre PHP 5.3 con codice spazio nomi. Eventuali esempi di codice sono molto incoraggiati e sono decisamente aperto a approcci diversi.

I vincoli preferiti per la soluzione sono:

  • La classe Dal può essere caricata automaticamente.
  • Le classi Dal non condividono lo stesso spazio per nomi esatti, ma condividono lo stesso nome di classe. Ad esempio, preferirei usare le classi denominate dBObject che usano spazi come come Vm\Db\MySql e Vm\Db\Oracle.
  • Le classi di tabelle non devono essere riscritte con una modifica del tipo DB.
  • Il tipo di DB appropriato viene determinato tramite solo una singola impostazione. Quell'impostazione è l'unica cosa che dovrebbe dover cambiare i tipi DB di scambio. Idealmente, il controllo delle impostazioni dovrebbe avvenire solo una volta per carico di pagina, ma sono flessibile su questo.

Aggiornamento finale

Grazie al suggerimento di Nikic, ho creato una classe di fabbrica astratta che carica il dBobject corretto e quindi avvolge i suoi metodi pubblici su una base 1: 1. Le classi di tabelle ora estendono la fabbrica anziché la classe DBObject.

Questa configurazione ora mi permetterà di testare e utilizzare ogni classe DBObject senza preoccuparmi dei conflitti e mi consente di utilizzare più DBM alla volta. Mi permette anche di conservare il codice che suggerisce in un IDE per ogni classe di tabella perché estendono ciascuno l'involucro di fabbrica. L'uso di metodi di avvolgimento potrebbe non essere la soluzione perfetta, ma non si basa sull'eredità di classe dinamica, risolve il mio problema di progettazione, soddisfa le mie esigenze e funziona.

Nessuna soluzione corretta

Autorizzato sotto: CC-BY-SA insieme a attribuzione
scroll top