cari

Rumah  >  Soal Jawab  >  teks badan

php PDO menggantikan parameter tanpa nama ('?') dalam pertanyaan dengan nilai boleh diedit

<p>Saya ingin cara untuk menunjukkan rupa pertanyaan SQL apabila parameter tanpa nama (<kod>?</kod>) digantikan dengan parameter sebenar. </p><p> Ini adalah <strong>hanya</strong> untuk tujuan kebolehbacaan dan penyahpepijatan, dan tidak akan digunakan sebagai pertanyaan sebenar. </p> <p>Saya dapati fungsi ini berfungsi dalam kebanyakan kes: </p> <pre class="brush:php;toolbar:false;">return array_reduce($this->bindValues, function ($sql, $binding) { return preg_replace('/?/', is_numeric($binding) ? $binding : '"' . $binding . '"', $sql, 1); }, $this->query);</pre> <p>Ganti? lwn nilai sebenar: </p> <pre class="brush:php;toolbar:false;">$data = array( 'item' => '1, 'type' => 'Adakah anda ok.' );</pra> <pre class="brush:php;toolbar:false;">KEMASKINI set `list` `item`=?,`type`= WHERE (`id` = ?) ; KEMASKINI set `senarai` `item`="1",`type`="Adakah anda ok." DI MANA (`id` = 1) ;</pre> <p>Tetapi jika nilai mengandungi ? <pre class="brush:php;toolbar:false;">$data = array( 'item' => '1, 'type' => 'Adakah anda ok?' );</pra> <pre class="brush:php;toolbar:false;">KEMASKINI `list` set `item`="1",`type`="Adakah anda ok2" </pra> <p>Bagaimana saya boleh membuat ini supaya ia hanya mengikat? telah diganti. </p>
P粉654894952P粉654894952481 hari yang lalu539

membalas semua(1)saya akan balas

  • P粉619896145

    P粉6198961452023-09-03 10:06:17

    Mula-mula, pertimbangkan untuk menggunakan parameter bernama dan bukannya <代码>? . Dalam kes ini, anda tidak perlu menggantikan apa-apa: parameter yang dinamakan jelas dan agak mudah ditunjukkan dalam log, dan disokong oleh kebanyakan klien dbms untuk tujuan penyahpepijatan.

    Jika parameter yang dinamakan tidak boleh dilaksanakan (kerana asas kod semasa yang besar atau sebarang sebab lain), anda mempunyai dua pendekatan utama:

    1. Gunakan penghurai pertanyaan SQL. Ia akan menghasilkan hasil yang paling boleh dipercayai.
    2. Gunakan sejenis "pengganti" yang ditulis sendiri. Keputusannya tidak akan menjadi ideal atau boleh dipercayai sepenuhnya, tetapi ia harus pantas dari segi prestasi dan pembangunan.

    Jika anda memilih cara yang kedua, berikut ialah contoh cara melakukannya dengan cepat dan kotor:

    Ganti dalam pelbagai langkah:

    1. Dengan menambah ? 替换为其他极不可能出现在参数或查询中的内容来准备参数。例如?.
    2. Gunakan ungkapan biasa untuk menggantikan parameter, ini akan sepadan dengan ?,但不会匹配第一步中的替换。如果用 ? 替换,则为 (?
    3. Masukkan semua ? 替换为 ? ​​dalam keputusan.

    Nota: Hasil penggantian ini seharusnya tidak digunakan sebagai pertanyaan dalam program. Penggantian ini berpotensi untuk melaksanakan mana-mana atau semua perkara berikut:

    • Suntikan SQL,
    • Jika pertanyaan awal mengandungi ? sebagai parameter (cth. dalam ulasan), hasilnya tidak tepat,
    • Jika pertanyaan awal atau mana-mana parameter mengandungi rentetan gantian (dalam kes kami ?), hasilnya tidak akan tepat.
    <?php
    $query = 'UPDATE `list` set `item`=?,`type`=? WHERE  (`id` = ?);';
    $params = array(
        'item' => '1',
        'type' => 'Are you o\'k?',
        'id'   => 2
    );
    
    function substitute_params($query, $params) {
        $prep_params =  str_replace(array("'","?"),array("''","\?"),$params);
        $query = array_reduce($prep_params, function ($interm, $param) {
            return preg_replace('/(?<!\\)\?/m', 
                is_numeric($param) ? $param : '\'' . $param . '\'', 
                $interm, 
                1);
        }, $query);
        return "-- Not to be used as a query to database. For demonstration purposes only!\n"
          .str_replace("\?", "?", $query);
    }
    echo substitute_params($query, $params);
    ?>
    

    Keluaran:

    -- Not to be used as a query to database. For demonstration purposes only!
    UPDATE `list` set `item`=1,`type`='Are you o''k?' WHERE  (`id` = 2);
    

    Sunting: Untuk mencuba dan mengurangkan kesan tanda soal di dalam rentetan tetap dan nama yang dipetik, anda boleh cuba menggunakan pengganti ini:

            return preg_replace('/^([^"\'`]*?(?:(?:`[^`]*?`[^"\'`]*?)*?(?:"[^"]*?"[^"\'`]*?)*?(?:\'[^\']*?\'[^\'"`]*?)*?)*?)(?<!\\)\?/m', 
                ''.(is_numeric($param) ? $param : '\'' . $param . '\''), 
                $interm, 
                1);
    

    Ia hanya menggantikan "`' 引用的块之外的 ? di luar blok yang disebut dengan "`'.

    Anda boleh melihat demo di sini.

    Sila ingat bahawa ini bukan penghurai sepenuhnya. Sebagai contoh, ia tidak tahu tentang ulasan. Jadi kemungkinan penggantian yang salah tetap tinggi.

    balas
    0
  • Batalbalas