(名前付きprintfスタイルのパラメーターを持つSQLクエリと連想配列が与えられた場合)名前付きパラメーターを(SQL準備済みステートメントの)疑問符に置き換え、配列を再配置できるPHP関数を作成しようとしています。クエリに表示される順序で。
動作する次のコードを作成しましたが、コメント内に表示される名前付きパラメーターを無視するようにこのコードを拡張したいと思います。
function sqlprintfn($sql, array $args = array()) {
$ordered_args = array();
static $formats = array('b','c','d','e','E','u','f','F','g','G','o','s','x','X');
$regex = sprintf('/(\?\(([a-zA-Z_]\w*)\)([%s]))/', implode('', $formats));
// Find the next named argument. Each search starts at the end of the previous replacement
for ($pos = 0; preg_match($regex, $sql, $match, PREG_OFFSET_CAPTURE, $pos);) {
$arg_pos = $match[0][1];
$arg_len = strlen($match[0][0]);
$arg_key = $match[2][0];
$arg_format = $match[3][0];
// Programmer did not supply a value for the named argument found in the format string
if (!array_key_exists($arg_key, $args)) {
trigger_error(sprintf('%s(): Missing argument \'%s\'', __FUNCTION__, $arg_key), E_USER_WARNING);
return false;
}
array_push($ordered_args, $args[$arg_key]);
// Replace the named argument with a question mark
$sql = substr_replace($sql, $replace = '?', $arg_pos, $arg_len);
$pos = $arg_pos + strlen($replace); // skip to end of replacement for next iteration
}
return array_merge((array) $sql, $ordered_args);
}
私が達成しようとしているものの例として:
$sql = 'SELECT id FROM users WHERE username = ?(username)s AND type = ?(type)s';
$params = array('type' => 'admin', 'username' => 'bob', email => 'bob@domain.com');
print_r(sqlprintfn($sql, $params));
出力する必要があります:
Array
(
[0] => 'SELECT id FROM users WHERE username = ? AND type = ?',
[1] => 'bob',
[2] => 'admin'
)
と:
$sql = 'SELECT id FROM users WHERE /* email = ?(email)s AND */ username = ?(username)s AND type = ?(type)s';
$params = array('type' => 'admin', 'username' => 'bob', email => 'bob@domain.com');
print_r(sqlprintfn($sql, $params));
出力する必要があります:
Array
(
[0] => 'SELECT id FROM users WHERE /* email = ?(email)s AND */ username = ? AND type = ?',
[1] => 'bob',
[2] => 'admin'
)
また、$sql 変数は複数行である可能性があることに注意してください。