Reputation: 4232
I want to make a db_queryf
function for my database abstraction. It will work somewhat like sqlite3_mprintf
from SQLite: db_queryf('select * from pages where name=%q', $_GET['name'])
, where %q will produce a properly escaped string. What is the proper way of making printf-like functions in PHP? Is there any helper functions for that or I should parse it myself?
Upvotes: 0
Views: 704
Reputation: 5796
okay, since I had exactly the same problem, I gave it a shot, and it seems to work quite nicely.
The following function sits inside a database wrapping class, and expects to be called like printf, where %%
is transformed to a literal %, %e
marks a string argument to be escaped, and %u
marks a string argument to taken as-is.
LOGDB
is a second database wrapping class, that is responsible for catching and logging all kinds of errors.
public static function query($format)
{
$query = $format . ' ';
$argc = func_num_args();
$argv = func_get_args();
$index_query = 0;
$index_args = 1;
while (($index_query = strpos($query, '%', $index_query)) !== false)
{
switch ($query[$index_query + 1])
{
case '%':
$query = substr_replace($query, '', $index_query, 1);
$index_query++;
break;
case 'e':
if ($index_args >= $argc)
{
LOG::failedQuery($format, "not enough arguments for format");
return false;
}
$query = substr_replace($query, DB::escape($argv[$index_args]), $index_query, 2);
$index_query += strlen($argv[$index_args]);
$index_args++;
break;
case 'u':
if ($index_args >= $argc)
{
LOG::failedQuery($format, "not enough arguments for format");
return false;
}
$query = substr_replace($query, $argv[$index_args], $index_query, 2);
$index_query += strlen($argv[$index_args]);
$index_args++;
break;
default:
LOG::failedQuery($format, "unknown control sequence '%" . $query[$index_query + 1] . "'");
return false;
}
}
if ($index_args != $argc)
{
LOG::failedQuery($format, "too many arguments for format");
return false;
}
$res = mysqli_query(self::$handle, $query);
if (!$res)
LOGDB::failedQuery($query, mysqli_error(self::$handle));
return $res;
}
Note: the code is mostly untested, chances are, it contains a bunch of bugs. use with caution :)
Upvotes: 0
Reputation: 20267
Use PDO prepared statements. Replacing into the string isn't good enough, you should be sanitizing.
Upvotes: 1
Reputation: 70460
I am confused... (s)printf
plainly allready exists, and you probably want to use SQLite3Stmt::bindValue
more for this, unless you want to end up in escaping / sql-injection hell..
Upvotes: 2
Reputation: 131871
sprintf('select * from pages where name=\'%s\'', $_GET['name']);
Its very important, that you sanitize everything in $_GET
, before you use it!
Upvotes: 0