Basically, I want to see if the two objects have matching properties (without hardcoding the properties themselves into the algorithm) and do some actions.
Sì, questo aiuta. La risposta basata sull'ipotesi che ho iniziato non sarebbe stata sufficiente. Ma KISS - mantenerlo semplicemente stupido - si applica ancora qui, IMO. Tenerlo breve e al punto, non è necessario forzarlo in un modello di progettazione se non si adatta naturalmente.
Consente di utilizzare una funzione di linguaggio speciale a nostro vantaggio. PHP consente di chiamare l'accesso dinamico agli attributi, con i nomi memorizzati come stringhe nelle variabili. Spesso è disapprovato in PHP, ma a volte è anche la soluzione più semplice. Ad esempio, in questo pseudocodice:
$attribs = array(
array('User' => 'reads_articles', 'Content' => 'is_article'),
array('User' => 'reads_books', 'Content' => 'is_book'),
);
class User {
function can_access(Content) {
foreach ($attribs as $reqs) {
if (!property_exists(self, $reqs['User'])) {
throw Exception("User is missing {$reqs['User']}");
}
if (!property_exists(Content, $reqs['Content'])) {
throw Exception("Content is missing {$reqs['Content']}");
}
if (self->{$reqs['User']} && Content->{$reqs['Content']}) {
return true;
}
}
return false;
}
reads_articles = true;
reads_books = true;
}
(Attenzione: non verificato, e so di avere una parte della sintassi errata (come ad esempio non nominare l'argomento Content, e dubito che lo scope sia giusto)).
Ci sono 3 possibili fonti per $attribs
a cui posso pensare. Ecco alcuni ulteriori pensieri su ciascuno:
- Hardcoded nella sorgente, come sopra
- Vantaggi: è proprio lì . Per la manutenzione, è molto facile vedere da dove proviene. Anche in un altro file, non devi cambiare mentalmente il contesto per ottenerlo.
- Svantaggi: è statico. Tutte le classi
User
e Content
devono definire ogni singolo, a meno che can_access
non venga modificato per accettare che "mancante" significhi "falso".
- Caricato da una tabella di database
- Vantaggi: In parole semplici, è molto più flessibile e più facile da estendere in futuro poiché l'interfaccia per utilizzare il database è già presente.
- Svantaggi: leggendo il codice, ora devi anche guardare il database per capire quali attributi saranno usati insieme. È anche più facile trascurarlo quando ne aggiungi uno nuovo.
- Derivato dal riflesso, esaminando le classi
- Vantaggi: i nuovi attributi sono inclusi automaticamente e le "regole" per determinare quali vanno insieme sono piuttosto semplici.
- Svantaggi: le regole per l'associazione degli attributi potrebbero essere skin-deep (
is_letter
/ sends_letters
non si adatta, per esempio), e c'è la possibilità che possano eguagliare qualcosa che non dovrebbero comunque. La programmazione "Meta" come questa è anche meno ovvia delle altre due, dal momento che tende ad essere usata meno spesso, quindi dovrebbe essere documentata abbastanza bene.
Gli svantaggi dell'utilizzo di un database sono così limitati che è così che andrei con esso, a meno che non fossi molto sicuro che questo insieme di attributi fosse improbabile che cambiasse o che il progetto non avesse già un database - quindi potrei vai con la prima opzione, hardcoding da qualche parte. Almeno con esso già in una forma semi-tabulata del genere, sarebbe semplice convertire in una tabella di database, se necessario.
Il fatto di dedurlo attraverso il pattern matching deve essere molto ben definito, quindi lo eviterei il più possibile. IMO rientra nella categoria "trucco ordinario" che raramente è più utile di altri metodi, fa alla possibilità di falsi positivi e probabilmente richiede documentazione aggiuntiva.
Ora, c'è un'opzione a metà strada che penso dovrebbe essere usata al posto degli attributi direttamente sulla classe:
class User {
$permissions = array(
'reads_articles' => true,
'reads_books' => true,
);
}
In questo modo, non c'è sovrapposizione con i normali attributi utente, ed è ovvio quali sono importanti. Le avvertenze su come per accoppiarle con quelle sul contenuto sono ancora valide, quindi uno dei precedenti 3 metodi sarebbe ancora necessario. Tuttavia, dalla domanda, non sono sicuro se ciò funzionerebbe per quello che hai in mente.
(Nota a margine, poiché potrebbe non essere ovvio - sto cercando di mantenere questo aspetto leggermente generico, dal momento che non sono sicuro che le autorizzazioni di cui parli siano a livello di classe o di istanza. di quanto sopra può essere fatto in entrambi i modi.)