php PDO replace anonymous parameter ('?') in query with editable value
P粉654894952
2023-09-02 11:38:14
<p>I would like a way to show what the SQL query looks like when the anonymous parameters (<code>?</code>) are replaced with actual parameters. </p><p>
This is <strong>only</strong> for readability purposes and debugging, and will not be used as an actual query. </p>
<p>I found this function works in most cases: </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>Replace? and actual value: </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>But if the value contains ? I end up with: </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>How can I make this so it only binds? has been replaced. </p>
First, consider using named parameters instead of ? 代码>. In this case you don't need to replace anything: the named parameters are clear and fairly easy to show in the logs, and are supported by most dbms clients for debugging purposes.
If named parameters are not feasible (due to the size of your current codebase or any other reason), you have two main approaches:
If you choose the latter approach, here is an example of how to do it quickly and dirty:
Replace in multiple steps:
?
with something else that is highly unlikely to appear in the parameter or query. For example\?
.?
, but will not match the substitution in the first step. If replaced with\?
, it is(?
\?
in the result with?
.NOTE: The results of this substitution should never be used as a query in a program. This replacement has the potential to implement any or all of the following:
?
instead as a parameter (e.g. in a comment), the results are inaccurate,\?
in our example), the results will be inaccurate.Output:
Edit: To try to reduce the impact of question marks within constant strings and quoted names, you can try using this replacement:
It only replaces
?
outside the block quoted with"`'
.You can view the demo here.
Please keep in mind that this is not a fully fledged parser. For example, it doesn't know about comments. So the possibility of incorrect substitution remains high.