Mengevaluasi kumpulan data dengan rumus string di php


9

Saya ditugaskan untuk memperbarui beberapa kondisi dalam suatu aplikasi. Saya memiliki satu set data untuk dievaluasi, dan telah di-hard-coded dalam aplikasi dengan cara berikut:

$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;

dan seterusnya...

Ini adalah mimpi buruk untuk dipertahankan di banyak tempat.

Apa yang saya cari pada dasarnya adalah membuat beberapa cara untuk mengirimkan string kueri untuk mengevaluasi data. Untuk memulai formula sederhana dapat didefinisikan sebagai array

$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]);
    }
}

Ini kemudian dapat diperpanjang dan disebut secara rekursif

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

tetapi apa yang saya cari pada dasarnya adalah untuk menyimpan formula aa string, seperti:

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

di mana [] akan mengidentifikasi kunci array

atau mungkin sesuatu seperti di Excel

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

Apakah ada solusi bersih untuk melakukan ini? Saya punya ide bagaimana membangun seluruh perpustakaan untuk itu, mungkin di masa depan.

Saya tidak ingin menambahkan ketentuan baru ke kode setiap waktu. Mereka sudah ada di seluruh aplikasi. Akan lebih baik untuk menyimpannya dalam konfigurasi dan memperluas atau memodifikasi di satu tempat.

Setiap bantuan sangat dihargai.


1
Menulis evaluator adalah tugas yang kompleks, tetapi Anda mungkin melihat memperluas jawaban ircmaxell untuk pertanyaan ini untuk menangani dan / atau dan string juga; atau lihat mesin Penghitung dalam sesuatu seperti PHPExcel
Mark Baker

1
Saya kira solusi "bersih" akan mengatur kelas dengan fungsi yang berbeda dan memasukkannya ke dalam beberapa file. Untuk menyimpan kode sebagai string dan mengevaluasinya nanti, PHP menawarkan eval().

1
Terima kasih @MarkBaker, saya mungkin melihatnya. Tidak persis apa yang saya cari kamu. Saya tidak benar-benar ingin menggunakan eval (), ini mungkin terlalu berbahaya, karena formula itu akan digunakan oleh pengguna. Ini harusnya lebih mudah.
Pawel Jankowski

3
Berhati-hatilah karena menciptakan "efek platform dalam". Sulit membayangkan dari apa yang telah Anda tunjukkan sejauh ini sehingga Anda akhirnya akan menyimpan banyak baris kode. Anda mungkin tidak memilih semua sintaks PHP, tetapi ini adalah standar yang dapat dipahami oleh pengembang PHP (atau C ++ atau pengembang Java). Jadi walaupun ini sepertinya hal yang menyenangkan untuk dicoba, mungkin lebih baik untuk bereksperimen terlebih dahulu pada proyek sampingan skala kecil. Jika berhasil di sana, maka pertimbangkan untuk memasukkannya ke dalam proyek besar.
John Doe

1
Seorang evaluator RPN akan menjadi tugas yang lebih sederhana untuk ditulis dan dipelihara. Ini sangat kuat dan ada sedikit hal yang bisa Anda salah. Itu kurang ramah pengguna sebagai pemikiran bahasa.
Scara95

Jawaban:


1

Jadi ini hanya solusi cepat, tetapi bekerja untuk saya sekarang.

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

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

Jika ada [a] dalam rumus itu akan diperlakukan sebagai kunci larik.

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);
    }
}

Dalam solusi ini akan bekerja dengan rumus seperti:

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

Bukan apa yang saya inginkan, tetapi melakukan pekerjaan, dan tidak begitu mengerikan (saya harap). Perlu pengecekan input dan penanganan kesalahan, tetapi ini hanyalah sebuah contoh.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.