Set di dati di valutazione con una formula di stringa in php


9

Mi è stato assegnato il compito di aggiornare alcune condizioni in un'applicazione. Ho un set di dati da valutare ed è stato codificato nell'applicazione nel modo seguente:

$arr = array(
'a' => 'apple',
'b' => 'orange',
'c' => 1,
'd' => 2,
'e' => 5,
'f' => 'green',
'g' => 'red',
'h' => 'yellow',
)

$res1 = ($arr['a'] == 'apple') ? TRUE : FALSE;
$res2 = (($arr['b'] == $arr['f']) && ($arr['c'] < $arr['d']) ? TRUE : FALSE;
$res3 = (($arr['e'] == '5') && $res2) ?TRUE : FALSE;

e così via...

È un incubo da mantenere in molti luoghi.

Quello che sto essenzialmente cercando è di fare un modo per passare la stringa di query per valutare i dati. Per iniziare una semplice formula potrebbe essere definita come una matrice

$formula = ['a', '=', 'apple'];

function query($formula, $arr) {
    switch ($formula[1]) {
        case '=':
            return ($arr[$formula[0]] == $formula[2]);
        case '!=':
            return ($arr[$formula[0]]!= $formula[2]);
        case '>':
            return ($arr[$formula[0]] > $formula[2]);
        case '<':
            return ($arr[$formula[0]] == $formula[2]);
    }
}

Questo quindi potrebbe essere esteso e chiamato in modo ricorsivo

$formula = [['a','=','apple'], 'AND', ['e','<','10']]

ma quello che sto essenzialmente cercando è memorizzare formule come stringhe, come:

"((([a]="orange") OR ([c]<"4")) AND ([g]="red"))"

dove [] identificherebbe le chiavi dell'array

o forse qualcosa del genere in Excel

"AND(OR(IF('a'='orange'),IF('c'<4)),IF('g'='red'))"

C'è qualche soluzione pulita per farlo? Ho un'idea di come costruire un'intera libreria per questo, forse in futuro.

Non voglio aggiungere nuove condizioni al codice ogni volta. Sono già in tutta l'applicazione. Sarebbe meglio memorizzarlo nella configurazione ed estenderlo o modificarlo in un unico posto.

Qualsiasi aiuto molto apprezzato.


1
Scrivere un valutatore è un compito complesso, ma potresti dare un'occhiata all'estensione della risposta di ircmaxell a questa domanda per gestire e / o stringhe; oppure guarda il motore di calcolo in qualcosa come PHPExcel
Mark Baker,

1
Immagino che una soluzione "pulita" sarebbe quella di creare una classe con diverse funzioni e includerla in diversi file. Per archiviare il codice come stringa e valutarlo in seguito, offre PHP eval().

1
Grazie @MarkBaker, potrei dare un'occhiata a quelli. Non è esattamente quello che sto cercando. Non voglio davvero usare eval (), questo potrebbe essere troppo pericoloso, poiché quelle formule verranno utilizzate dagli utenti. Questo dovrebbe essere più sicuro.
Pawel Jankowski il

3
Fai attenzione alla creazione di un "effetto di piattaforma interna". È difficile immaginare da ciò che ci hai mostrato finora che potresti finire per salvare molte righe di codice. Potresti non preferire tutta la sintassi di PHP, ma è uno standard che può comprendere qualsiasi sviluppatore PHP (o sviluppatore C ++ o Java). Quindi, mentre questa sembra una cosa divertente da provare, potrebbe essere meglio sperimentarla prima su un progetto laterale su scala ridotta. Se funziona lì, prendi in considerazione l'idea di inserirlo nel grande progetto.
John Doe,

1
Un valutatore di RPN sarebbe un compito più semplice da scrivere e mantenere. È piuttosto potente e ci sono meno cose che puoi sbagliare. È meno facile da usare come un linguaggio pensato.
Scara95,

Risposte:


1

Quindi questa è solo una soluzione rapida, ma funziona per me in questo momento.

$arr = array('a' => 'red','b' => 'blue');

$formula = ['[a]', '=', 'red'];

Se la formula è [a], verrà trattata come chiave dell'array.

function query($formula, $arr) {

    $query_operator=$formula[1];

    if (is_array($formula[0])) {
        //recursive call
        $query_left = query($formula[0], $arr);
    } else {
        //extracting string between brackets
        preg_match("/\[([^\]]*)\]/", $formula[0], $match);
        $query_left = $match ? $arr[($match[1])] : $formula[0];
    }

    if (is_array($formula[2])) {
        //recursive call
        $query_right = query($formula[2], $arr);
    } else {
        //extracting string between brackets
        preg_match("/\[([^\]]*)\]/", $formula[2], $match);
        $query_right = $match ? $arr[($match[1])] : $formula[2];
    }


    switch ($query_operator) {
        case '=':
            return ($query_left == $query_right);
        case '!=':
            return ($query_left != $query_right);
        case '>':
            return ($query_left > $query_right);
        case '<':
            return ($query_left == $query_right);
        case 'AND':
            return ($query_left && $query_right);
        case 'OR':
            return ($query_left || $query_right);
    }
}

In questa soluzione funzionerà con una formula come:

$formula = [['[a]', '=', 'red'], 'AND', ['[b]', '=', 'blue']];

Non è esattamente quello che volevo, ma fa il lavoro, e non è così terribile (spero). Ha bisogno di alcuni controlli di input e gestione degli errori, ma questo è solo un esempio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.