function sql_placeholder_ex($tmpl, $args, &$errormsg) { // Запрос уже разобран?.. Если нет, разбираем. if (is_array($tmpl)) { $compiled = $tmpl; } else { $compiled = sql_compile_placeholder($tmpl); } list($compiled, $tmpl, $has_named) = $compiled; // Если есть хотя бы один именованный placeholder, используем // первый аргумент в качестве ассоциативного массива. if ($has_named) { $args = @$args[0]; } // Выполняем все замены в цикле. $p = 0; // текущее положение в строке $out = ''; // результирующая строка $error = false; // были ошибки? foreach ($compiled as $num => $e) { list($key, $type, $start, $length) = $e; // Pre-string. $out .= substr($tmpl, $p, $start - $p); $p = $start + $length; $repl = ''; // текст для замены текущего placeholder-а $errmsg = ''; // сообщение об ошибке для этого placeholder-а do { // Это placeholder-константа? if ($type === '#') { $repl = @constant($key); if (NULL === $repl) { $error = $errmsg = "UNKNOWN_CONSTANT_{$key}"; } break; } // Обрабатываем ошибку. if (!isset($args[$key])) { $error = $errmsg = "UNKNOWN_PLACEHOLDER_{$key}"; break; } // Вставляем значение в соответствии с типом placeholder-а. $a = $args[$key]; if ($type === '') { // Скалярный placeholder. if (is_array($a)) { $error = $errmsg = "NOT_A_SCALAR_PLACEHOLDER_{$key}"; break; } $repl = preg_match('/^\\d+$/', $a) ? $a : "'" . addslashes($a) . "'"; break; } // Иначе это массив или список. if (!is_array($a)) { $error = $errmsg = "NOT_AN_ARRAY_PLACEHOLDER_{$key}"; break; } if ($type === '@') { // Это список. foreach ($a as $v) { $repl .= ($repl === '' ? "" : ",") . "'" . addslashes($v) . "'"; } } elseif ($type === '%') { // Это набор пар ключ=>значение. $lerror = array(); foreach ($a as $k => $v) { if (!is_string($k)) { $lerror[$k] = "NOT_A_STRING_KEY_{$k}_FOR_PLACEHOLDER_{$key}"; } else { $k = preg_replace('/[^a-zA-Z0-9_]/', '_', $k); } $repl .= ($repl === '' ? "" : ", ") . $k . "='" . @addslashes($v) . "'"; } // Если была ошибка, составляем сообщение. if (count($lerror)) { $repl = ''; foreach ($a as $k => $v) { if (isset($lerror[$k])) { $repl .= ($repl === '' ? "" : ", ") . $lerror[$k]; } else { $k = preg_replace('/[^a-zA-Z0-9_-]/', '_', $k); $repl .= ($repl === '' ? "" : ", ") . $k . "=?"; } } $error = $errmsg = $repl; } } elseif ($type === '&') { // Это список. foreach ($a as $v) { $repl .= ($repl === '' ? "" : ",") . '`' . addslashes($v) . '`'; } } } while (false); if ($errmsg) { $compiled[$num]['error'] = $errmsg; } if (!$error) { $out .= $repl; } } $out .= substr($tmpl, $p); // Если возникла ошибка, переделываем результирующую строку // в сообщение об ошибке (расставляем диагностические строки // вместо ошибочных placeholder-ов). if ($error) { $out = ''; $p = 0; // текущая позиция foreach ($compiled as $num => $e) { list($key, $type, $start, $length) = $e; $out .= substr($tmpl, $p, $start - $p); $p = $start + $length; if (isset($e['error'])) { $out .= $e['error']; } else { $out .= substr($tmpl, $start, $length); } } // Последняя часть строки. $out .= substr($tmpl, $p); $errormsg = $out; return false; } else { $errormsg = false; return $out; } }
function sql_placeholder() { $args = func_get_args(); $tmpl = array_shift($args); if (is_array($tmpl)) { $compiled = $tmpl; } else { $compiled = sql_compile_placeholder($tmpl); } $has_named = $compiled[2]; $tmpl = $compiled[1]; $compiled = $compiled[0]; if ($has_named) { $args = @$args[0]; } $p = 0; $out = ""; foreach ($compiled as $e) { $length = $e[3]; $start = $e[2]; $type = $e[1]; $key = $e[0]; $out .= substr($tmpl, $p, $start - $p); $p = $start + $length; $repl = ""; if ($type === "#") { while (NULL === ($repl = @constant($key))) { $repl = "UNKNOWN_CONSTANT_" . $key; } } else { if (isset($args[$key])) { $repl = "UNKNOWN_PLACEHOLDER_" . $key; } else { $a = $args[$key]; if ($type === "") { if (is_array($a)) { $repl = "NOT_A_SCALAR_PLACEHOLDER_" . $key; break; } else { $repl = "'" . addslashes($a) . "'"; } } else { if (is_array($a)) { $repl = "NOT_AN_ARRAY_PLACEHOLDER_" . $key; } else { if ($type === "@") { foreach ($a as $v) { $repl .= ($repl === "" ? "" : ",") . "'" . addslashes($v) . "'"; } } else { if ($type === "%") { foreach ($a as $k => $v) { if (is_string($k)) { $k = "NOT_A_STRING_KEY_" . $k . "_FOR_PLACEHOLDER_{$key}"; } else { $k = preg_replace("/[^a-zA-Z0-9_-]/", "_", $k); } $repl .= ($repl === "" ? "" : ", ") . $k . "='" . @addslashes($v) . "'"; } } } if (false) { } } } } } } $out .= $repl; }