Náhrada placeholderů

Školení, která pořádám

V PDO, ale i v dalších databázových rozhraních, je k dispozici mechanismus vázání proměnných. Jak by se dalo něco takového udělat v PHP?

Problém „nahradit v řetězci určité značky jejich hodnotou“ je samozřejmě obecnější, ale u databází se dobře představuje. K řešení se nabízí funkce preg_replace_callback, která při nalezení zadané masky zavolá uživatelskou funkci. Této uživatelské funkci je ale nejprve potřeba nějak předat seznam dvojic k nahrazení. Použití globálních proměnných by zrovna čisté nebylo stejně jako vytvoření funkce přímo obsahující seznam, takže by se uživatelská funkce mohla nejprve inicializovat (seznam by si uložila do statické proměnné). Ani to ale není zrovna elegantní, takže jako nejlepší mi vychází použít pro volanou funkci metodu objektu, kterému seznam dvojic nejprve nastavíme. Typ callback totiž umožňuje kromě jména funkce předat i pole array($objekt, 'metoda'), což využijeme:

<?php
class DB {
    private $replace;
    
    public function substitute($query, $replace = array()) {
        $this->replace = $replace;
        return preg_replace_callback('~:(\\w+)~', array($this, 'callback'), $query);
    }
    
    private function callback($match) {
        $return = $this->replace[$match[1]];
        return (is_int($return) ? $return : "'" . mysql_real_escape_string($return) . "'");
    }
    
}

$db = new DB;
echo $db->substitute("SELECT * FROM tabulka WHERE sloupec = :a", array("a" => 5));
?>

Pokud by se klíče v poli záměn shodovaly se značkami (nebo by se na ně daly snadno převést), dala by se využít i funkce strtr:

<?php
function substitute($query, $replace = array()) {
    $pairs = array();
    foreach ($replace as $key => $val) {
        $pairs[":$key"] = (is_int($val) ? $val : "'" . mysql_real_escape_string($val) . "'");
    }
    return strtr($query, $pairs);
}
echo substitute("SELECT * FROM tabulka WHERE sloupec = :a", array("a" => 5));
?>

Prvně popsaný způsob je ale robustnější, dovoluje nám snadno reagovat např. i na nedefinované značky, to by se u druhého způsobu muselo řešit odděleně.

Jakub Vrána, Výuka, 29.5.2006, diskuse: 2 (nové: 0)

Diskuse

@ss@ssIn:

"Typ callback totiž umožňuje kromě jména funkce předat i pole array($objekt, 'metoda'), což využijeme..."

tusim sa naucim zaklady... bo taketo veci som s radostou pri citani manualu preskakoval...

ikona Martin Zvarík:

Dělat s pomocí preg_replace SQL příkazy je šílenost... Vypadá to sice přehledně, ale efektní to 100% není. To už raději se strpos()... Doporučuji se spokojit s sprintf() a vytvořit vlastní funkci.

Diskuse je zrušena z důvodu spamu.

avatar © 2005-2024 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.