Мне надоело писать запросы на моем PHP как:
"WHERE '" . Database::escape($var) . "'";
Функция escape() просто вызывает mysql_real_escape_string() - но она есть, поэтому я могу позже расширить поддержку других баз данных.
Наличие одиночных строк кавычек в запросе делало мой код более загроможденным. Поэтому моя идея заключалась в создании другой функции в моем классе базы данных для "подготовки" переменной для запроса:
static public function prepare($var)
{
if (is_object($var) || is_array($var) ) {
return " '" . Database::escape(serialize($var)) . "' ";
} else if (is_bool($var)) {
return ' ' . (int)$var . ' ';
} else if (is_int($var)) {
return ' ' . $var . ' ';
} else if (is_string($var) || is_float($var)) {
return " '" . Database::escape($var) . "' ";
} else {
throw new Exception('Unsupported variable type [' . gettype($var) . ']');
}
}
Теперь преимущество здесь в том, что мне не нужно беспокоиться о том, какие переменные я передаю в запрос. Однако возникает два вопроса:
Вы ищете a) pepared statements и b) уровень абстракции базы данных (например, PDO).
То, что вы пытаетесь сделать самостоятельно, уже было решено, вы не должны откатывать свою собственную реализацию.
Если вы спуститесь по этой дороге, вы заметите, что это:
"... WHERE '" . Database::escape($var) . "'"
бессмысленна и опасна. Четкое разделение кода и параметров SQL требует, чтобы вы были более явными и обеспечивали вам безопасную сторону от SQL-инъекции в одно и то же время:
"--- WHERE SomeField = ?" /* the parameter (?) will be filled elsewhere */
Стоит отметить, что истинная независимость поставщика в области базы данных находится где-то между жестким и невозможным, в зависимости от ваших потребностей и приоритетов. Поэтому попытка написать переносимый SQL может оказаться бесполезной, если вы не готовы пожертвовать много. Для MySQL он запускается даже с помощью предложения LIMIT, которое вы не сможете подключить, скажем, к SQL Server.
Да, просто используйте параметризованные запросы, и он будет просто работать. Это правильное решение, и это не ужасно сложно.
В PHP используйте PDO для этого, его API гораздо более здравомыслящий, чем mysql_ или mysqli_, и, кроме того, он может генерировать исключения из ошибок и делать другие приятные вещи.
Вероятно, вы не должны этого делать. Вот почему: mysqli:: подготовить или PDO:: подготовить
Что касается самой функции, что произойдет, если у вас есть что-то, хранящееся в строке (скажем "5"
), которую вы хотите сохранить как int? Он все равно будет процитировать его.
Вы можете попробовать
$sql = "SELECT * FROM SomeTable WHERE userid = '{Database::prepare($userid}'";
чтобы облегчить проблемы с набором текста. Хотя мое предложение состоит в том, что если вы принимаете входные данные из формы, почему бы не настроить Database:: prepare() для запуска через $_REQUEST или $_POST, чтобы очистить их или выплеснуть копию?
Вот как я это делаю:
$safe_post = InputCleaner::clean($_POST);
$sql = "SELECT * FROM table WHERE userid = {$safe_post['userid']}";