2011-08-29 10 views
7

Nella nostra applicazione corrente Ho un rapporto che contiene qualcosa come:Come posso memorizzare uno stato condizionale PHP nel database per un uso successivo?

if($foo == 3 || $bar > 3) { 
    $e = someFunction(); 
}; 

ma per un client diverso la stessa espressione potrebbe essere:

if($foo == 3 || $bar == 5 && $foobar != 9) { 
    $e = someFunction(); 
}; 

C'è un modo straight-forward per memorizzare il due espressioni diverse, solo i bit

$foo == 3 || $bar > 3 OR $foo == 3 || $bar == 5 

nel database (MySQL) quindi non c'è bisogno di codificare tutte queste regole da parte del cliente o mantenere le versioni client dello stesso report. Sto cercando di capire se posso impostare una variabile o sostituire le condizioni. Qualcosa di simile:

$conditions = $row_rsConditions['condition_row'] //Get $foo == 3 || $bar > 3 from the DB and store it as $conditions 
if($conditions) { 
    $e = someFunction(); 
}; 

Ci potrebbero essere> 100 diversi client e ogni client potrebbe/avrebbe un diverso insieme di espressioni. Non sono sicuro del giusto/miglior modo per farlo.

UPDATE:

credo di capire i problemi che utilizzano la funzione eval() di PHP. Ma a causa del numero di possibili combinazioni mi sto proponendo di usare il DB per memorizzare le condizioni (non sono sicuro di usare eval())

Fa alcuna differenza (più sicuro) se non c'è un'interfaccia utente che scrive nel campo delle condizioni/tabella? Potrebbe essere qualcosa che gestiamo da soli.

+4

Che ne dici di salvare il codice nel database e successivamente caricarlo ed eseguirlo usando 'eval' ? Tu ci potrebbero essere problemi di sicurezza quando qualcuno inietta il database e ti fa valere il suo codice. – Nobody

+0

Quindi, la domanda è: per quali circostanze, gli operatori all'interno delle condizioni possono cambiare? – Deele

+5

Penso che sia un pessimo progetto archiviare la logica nel database, il database dovrebbe essere usato solo per i dati – Fivell

risposta

3

Sarei molto attento a memorizzare la logica nel database.

  1. il codice non è più tutto in un unico luogo.
  2. la logica nel database è improbabile che sia sottoposta al controllo del codice sorgente
  3. se si modifica il codice e si interrompe tutta la logica specifica del client, è necessario tornare al database e modificarlo per ogni client.
  4. altre persone potrebbero avere accesso al database e potrebbero modificare il codice in qualcosa di malevolo.

questa potrebbe non essere la soluzione migliore ma suggerirei di creare una classe base astratta, quindi ereditare da quella, una classe specifica per ogni client.

Qualsiasi funzione personalizzata può essere aggiunta come metodo alla classe base e sovrascritta per l'implementazione specifica del client.

utilizzare un'istruzione switch per creare un'istanza della classe in base a un id o nome del client (qualcosa che non cambia) già memorizzato nel database.

switch ($client_name) { 

case "abc ltd": 
    $customlogic = new CustomLogicAbc(); 
    break; 

case "zyx ltd": 
    $customlogic = new CustomLogicXyz(); 
    break; 

default: 
    $customlogic = new CustomLogicDefault(); 
    break; 

} 

if ($customlogic->doSomething($parm1, $parm2)) { 
    // custom logic has been applied 
} 
+0

Penso che il problema sia relativamente semplice, nel senso che sta solo andando a controllare quei due valori. Ma ha molte condizioni diverse su di loro che tutti dovrebbero essere codificati. Invece la parametrizzazione di questo richiede solo un'implementazione e il recupero delle condizioni come vuole. – Nobody

+0

Quindi, se ci sono più di 100 clienti questa opzione è ancora fattibile? Sono d'accordo con i tuoi punti # 1 e # 2. # 3 è su di noi per mantenere correttamente e # 4 - se possono cambiarlo, allora possono già fare molto più danni, giusto? – Jason

+0

dipende davvero da quanta logica personalizzata hai e quanto sia complessa. se si ha solo la dichiarazione 1 mostrata nell'esempio, potrebbe essere meglio memorizzare i parametri $ foo e $ bar nel database rispetto a ciascun record del client piuttosto che la logica effettiva stessa. Se hai molte dichiarazioni personalizzate e sono complesse, allora farei come ho fatto sopra, poiché è probabile che la logica diventi più complessa man mano che procedi, e aggiungerai anche altre cose personalizzate – bumperbox

2

di approfondire il mio commento:

Il tuo ultimo codice è quasi quello che volevo dire:

$conditions = $row_rsConditions['condition_row']; //Get "$foo == 3 || $bar > 3" 
if(eval("return (" . $conditions . ");")) { 
    $e = someFunction(); 
} 

Tuttavia io vi avverto di nuovo per ricordare il rischio di fare questo. Quando si utilizza il codice dal database, è probabile che vi siano errori. Almeno alcuni controlli di sicurezza dovrebbero essere eseguiti sui dati per evitare un uso improprio.

Un'altra opzione che è un po 'più complicata ma che non è soggetta a un uso improprio sarebbe codificare le condizioni. Come sembra che si confrontano solo 2 variabili con un valore di ciascuna si potrebbe risparmiare per ogni variabile qualcosa di simile:

0 != 
1 == 
2 >= 
3 <= 
4 > 
5 < 

Per salvare il rapporto e inoltre salvare il valore al quale deve essere confrontato. In questo modo non vi è alcuna esecuzione diretta del codice che viene salvato nel database.

+0

Estremamente pericoloso! – Gustav

+0

@Gustav - Non è sicuro perché aprirò un posto per consentire l'iniezione di codice o c'è qualcosa di più? – Jason

+0

@Jason La parte di iniezione PHP è la peggiore. – Gustav

0

nessuno può dirti come risolverlo perché nessuno sa requisiti funzionali e logica specifica della vostra applicazione ... Ma se il tempo di implementazione è importante per voi è possibile naturalmente provare a utilizzare evaluationg di espressioni dal database, ma fai attenzione e usa sanitazing di tutti i dati dal database ... C'è un esempio how to make php expressions and execute from database? - aggiungi solo più logica perché puoi avere condizioni multiple

Problemi correlati