La situazione : sto costruendo un framework di applicazioni PHP personalizzate. Ho implementato un pattern composito in modo da poter costruire un albero di oggetti che rappresenta la pagina da renderizzare. Esempio:
abstract class \Block\BlockAbstract {
protected _blocks = array();
public function __construct($properties);
public function getBlocks();
public function addBlock($block);
...
public function render();
}
Tutti i miei "blocchi" oggetto ereditano da questa classe astratta che sta funzionando alla grande e il rendering è stato un gioco da ragazzi con l'aiuto di una piccola ricorsione.
Il problema : Ho bisogno di un modo per convalidare quali classi di blocchi possono essere aggiunte ad altri blocchi. Ad esempio, ho 4 tipi di blocchi distinti che devo considerare. Tieni presente che TUTTI i blocchi ereditano da un singolo blocco astratto, queste sono classificazioni del comportamento delle classi concrete, da non confondere con gli abstract aggiuntivi:
-
Generico: a Generics può essere aggiunto qualsiasi altro tipo di blocco
-
Finale - Impossibile aggiungere blocchi figlio.
-
Padre - Un genitore è un blocco a cui può essere aggiunto solo un tipo specifico ma può essere aggiunto a qualsiasi generico
-
Bambino - Può essere aggiunto solo a un genitore specifico. Questo blocco può anche condividere le proprietà di un Generic, Parent o Final
Per riassumere l'obiettivo: dato un nome di classe di blocco concreto, generare un elenco di tutte le classi di blocchi concreti che possono essere aggiunte ad esso.
Soluzioni proposte finora :
Aggiungi una proprietà chiamata "blockClassification" al blocco astratto che la definisce come generica, finale, padre o figlio e codifica la logica in una funzione di convalida che viene chiamata nel da addBlock (blocco $) metodo.
Questa soluzione non mi piace per una serie di motivi, ma soprattutto non mi dà ancora un chiaro percorso per definire cosa possono essere concessi genitori e figli concreti. Ad esempio, ho una classe concreta \ Block \ Tabs che è un genitore. Può solo aggiungere blocchi \ Block \ Tabs \ Panel e \ Block \ Tabs \ Panel può essere aggiunto solo a \ Block \ Tabs . Ulteriori proprietà dovrebbero essere aggiunte per costruire quelle relazioni e queste proprietà potrebbero essere esaminate per ricavare la "classificazione dei blocchi" che rende questo approccio poco pratico.
Aggiungi la proprietà allowedChildTypes al blocco che definisce un elenco di classi concrete che possono essere aggiunte. Per facilità d'uso, i 2 valori hanno un significato specifico, un * che rappresenta tutti i tipi di blocco e il valore NULL che significa che non è possibile aggiungere alcun blocco. Per tutti gli altri casi viene fornita una stringa delimitata da nomi di classi e sono consentite solo le classi o le classi che ne ereditano
Sono propenso a questa direzione perché PHP mi fornisce l'operatore InstaceOf. Posso usarlo per fare i controlli, quando ho nuove classi concrete che estendono il set base, quel controllo restituirà gli stessi risultati della sua classe genitore. La mia unica esitazione è che mentre questo metodo risolve definitivamente il problema di "Dato un nome di classe di blocco concreto, genera un elenco di", sento che mi limiterà in futuro in quanto posso solo eseguire la ricerca lungo l'albero e non tornare indietro su. Cioè "Dato un nome classe di blocco figlio, genera un elenco di blocchi padre che può essere aggiunto a"
Sono sicuro di non essere il solo ad aver mai incontrato il problema, quindi la mia domanda alle masse è: qual è il modo migliore per affrontare / risolvere questo problema?
Informazioni aggiuntive:
Se ti stai chiedendo come ottenere una lista di tutte le classi in primo luogo, il framework implementa PSR-0 in modo da analizzare l'albero delle directory per ricavare tutti i nomi di classe, quindi istanzializzarli dinamicamente.
$allClassNames = scanDirectories(); // Returns array of strings ex: array('\Block\Classname1','\Block\Classname2');
foreach($allClassNames as $className){
$object = new $className();
}