Maison  >  Questions et réponses  >  le corps du texte

php PDO remplace le paramètre anonyme ('?') dans la requête avec une valeur modifiable

<p>Je voudrais un moyen de montrer à quoi ressemble la requête SQL lorsque les paramètres anonymes (<code>?</code>) sont remplacés par des paramètres réels. </p><p> Ceci est <strong>uniquement</strong> à des fins de lisibilité et de débogage, et ne sera pas utilisé comme une requête réelle. </p> <p>J'ai trouvé que cette fonction fonctionne dans la plupart des cas : </p> <pre class="brush:php;toolbar:false;">return array_reduce($this->bindValues, fonction ($sql, $binding) { return preg_replace('/?/', is_numeric($binding) ? $binding : '"' . $binding . '"', $sql, 1); }, $this->query);</pre> <p>Remplacer ? et valeur réelle : </p> <pre class="brush:php;toolbar:false;">$data = array( 'article' => '1, 'type' => 'Ça va.' );</pré> <pre class="brush:php;toolbar:false;">UPDATE `list` set `item`=?,`type`= OÙ (`id` = ?) ; MISE À JOUR `list` set `item`="1",`type`="Ça va." OÙ (`id` = 1) ;</pre> <p>Mais si la valeur contient ?, je me retrouve avec : </p> <pre class="brush:php;toolbar:false;">$data = array( 'article' => '1, 'type' => 'Ça va ?' );</pré> <pre class="brush:php;toolbar:false;">UPDATE `list` set `item`="1",`type`="Ça va2" OÙ (`id` = ?) ; ≪/pré> <p>Comment puis-je faire en sorte qu'il soit uniquement lié ? a été remplacé. </p>
P粉654894952P粉654894952436 Il y a quelques jours491

répondre à tous(1)je répondrai

  • P粉619896145

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

    Tout d'abord, envisagez d'utiliser des paramètres nommés au lieu de <代码> ? . Dans ce cas, vous n'avez rien à remplacer : les paramètres nommés sont clairs et assez faciles à afficher dans les journaux, et sont pris en charge par la plupart des clients dbms à des fins de débogage.

    Si les paramètres nommés ne sont pas réalisables (en raison d'une base de code actuelle volumineuse ou pour toute autre raison), vous avez deux approches principales :

    1. Utilisez l'analyseur de requêtes SQL. Cela produira les résultats les plus fiables.
    2. Utilisez une sorte de "remplacement" auto-écrit. Ses résultats ne seront jamais idéaux ni totalement fiables, mais il devrait être rapide tant en termes de performances que de développement.

    Si vous choisissez cette dernière méthode, voici un exemple de la façon de le faire rapidement et salement :

    Remplacez en plusieurs étapes :

    1. En ajoutant ? 替换为其他极不可能出现在参数或查询中的内容来准备参数。例如?.
    2. Utilisez une expression régulière pour remplacer le paramètre, cela correspondra ?,但不会匹配第一步中的替换。如果用 ? 替换,则为 (?
    3. Incluez tous les ? 替换为 ? dans les résultats.

    Remarque : Les résultats de ce remplacement ne doivent jamais être utilisés comme requêtes dans les programmes. Ce remplacement a le potentiel de mettre en œuvre tout ou partie des éléments suivants :

    • Injection SQL,
    • Si la requête initiale contient ? à la place comme paramètre (par exemple dans un commentaire), les résultats sont inexacts,
    • Si la requête initiale ou l'un des paramètres contient une chaîne de remplacement (dans notre cas ?), les résultats ne seront pas précis.
    <?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);
    ?>
    

    Sortie :

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

    Edit : Pour essayer de réduire l'impact des points d'interrogation à l'intérieur des chaînes constantes et des noms entre guillemets, vous pouvez essayer d'utiliser ce remplacement :

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

    Il remplace uniquement "`' 引用的块之外的 ? en dehors du bloc cité par "`'.

    Vous pouvez voir la démo ici.

    Veuillez garder à l'esprit qu'il ne s'agit pas d'un analyseur à part entière. Par exemple, il ne connaît pas les commentaires. La possibilité d’une substitution incorrecte reste donc élevée.

    répondre
    0
  • Annulerrépondre