php PDO 以可編輯值取代查詢中的匿名參數('?')
P粉654894952
P粉654894952 2023-09-02 11:38:14
0
1
535
<p>我想要一個方法來顯示 SQL 查詢在用實際參數取代匿名參數 (<code>?</code>) 時的外觀。 </p><p> 這<strong>僅</strong>用於可讀性目的和調試,不會用作實際查詢。 </p> <p>我發現這個函數在大多數情況下都有效:</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>更換?與實際值:</p> <pre class="brush:php;toolbar:false;">$data = array( 'item' => '1, 'type' => 'Are you ok.' );</pre> <pre class="brush:php;toolbar:false;">UPDATE `list` set `item`=?,`type`=? WHERE (`id` = ?) ; UPDATE `list` set `item`="1",`type`="Are you ok." WHERE (`id` = 1) ;</pre> <p>但如果該值包含 ?我最終得到的是:</p> <pre class="brush:php;toolbar:false;">$data = array( 'item' => '1, 'type' => 'Are you ok?' );</pre> <pre class="brush:php;toolbar:false;">UPDATE `list` set `item`="1",`type`="Are you ok2" WHERE (`id` = ?) ; </pre> <p>我怎麼能做到這一點,所以只能綁定?已被替換。 </p>
P粉654894952
P粉654894952

全部回覆(1)
P粉619896145

首先,考慮使用命名參數而不是? 代码>。在這種情況下,您不需要替換任何內容:命名參數清晰且相當容易在日誌中顯示,並且大多數 dbms 用戶端都支援用於偵錯目的。

如果命名參數不可行(由於目前程式碼庫較大或任何其他原因),您有兩種主要方法:

  1. 使用 SQL 查詢解析器。它將產生最可靠的結果。
  2. 使用某種自己寫的「替代者」。它的結果永遠不會是理想的或完全可靠的,但在性能和開發方面都應該很快。

如果您選擇後一種方式,這裡是如何快速且骯髒地完成它的範例:

分多個步驟進行替換:

  1. 透過將 ? 替換為其他極不可能出現在參數或查詢中的內容來準備參數。例如\?
  2. 使用正規表示式取代參數,這將符合 ?,但不會符合第一步中的替換。如果以 \? 替換,則為 (?
  3. #將結果中的所有 \? 替換為 ?

注意:此替換的結果不應永遠用作程式中的查詢。這種替代有可能實現以下任何或所有功能:

  • SQL 注入,
  • 如果初始查詢包含 ? 而不是作為參數(例如在註釋中),結果不準確,
  • 如果初始查詢或任何參數包含替換字串(在我們的範例中為 \?),結果將不準確。
<?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);
?>

輸出:

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

編輯:要嘗試降低常數字串和帶引號的名稱內問號的影響,​​您可以嘗試使用此替換:

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

它只會取代用 "`' 引用的區塊之外的 ?

可以在此處查看示範。

請記住,這不是完全成熟的解析器。例如,它不知道評論。因此錯誤替換的可能性仍然很高。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板