У меня есть класс для управления базой данных, и один из моих подклассов (тот, который определяет запрос) определяется таким образом (просто образец, многие другие функции фактически лишены для целей тестирования):
namespace Tests\SQL\Arguments { // SQL query class Query { public $attributes; // constructor for this object public function __construct() { if ($arguments = func_get_args()) { $this->attributes["query"] = current($arguments); if (sizeof($arguments) > 1) { $this->attributes["parameters"] = array_slice($arguments, 1, sizeof($arguments)); } return $this; } } } $query = new Query("INSERT INTO `clients/history` (`date`,`client`,`ammount`,`status`) VALUES (?,?,?,?);", date("Ymd H:i:s"), 57, 17852.25, "A"); print_r($query); }
Как вы можете видеть, я автоматически подбираю аргументы функции, поэтому я могу легко отделить запрос от своих пареметров во время построения. Помимо массовых действий INSERT/UPDATE/DELETE
, я хотел бы предоставить некоторую безопасность, например, предотвращать инъекции SQL и другие вещи.
Мой вопрос … учитывая эту структуру, когда я передаю эту структуру как ( просто простой пример, она будет работать по-другому, но эта действительна на данный момент ):
$this->queries["clients/history"]->execute($this->attributes["query"], $this->attributes["parameters"]);
Будет ли какой-либо другой способ использовать именованные параметры, такие как (:date,:client,:ammount,:status)
или использовать параметры вопросительного знака, такие как (?,?,?,?)
?
EDIT – лучшее объяснение
Извините за (кажущуюся) неясность, которую ставит мой вопрос. Мое намерение состоит в том, чтобы иметь механизм, подобный sprintf, но вместо хранения строки со всеми параметрами, сложенными в нее, я просто сохраняю запрос и параметры отдельно.
Это всего лишь класс Query. Также существует класс QueryGroup (для хранения запросов в группах), класс Manager (который хранит и управляет всеми подключениями к базе данных) и класс Connection (который отвечает за объединение всех запросов и групп запросов для данного соединения с базой данных).
Об именованных параметрах я не вижу проблемы с используемым методом, поскольку это работает, как я уже сказал, как функция sprintf
. Я поставлю либо вопросительные знаки, либо имена параметров в строке запроса.
Я хочу сделать разделение, чтобы обеспечить дополнительные возможности фильтрации, такие как экранирование или кавычки, чтобы предотвратить некоторые формы инъекций или саботаж против данной базы данных.
Метод execute()
который я раскрыл, является только бумажной копией метода execute()
PDO. То, что я пытаюсь определить, заключается в том, что в равной мере «безопасно» использовать именованные параметры или параметры вопросительных знаков (или, может быть, есть некоторые различия, которые я не вижу там).
Любой намек был бы весьма признателен 🙂
Разница между именованными неименованными параметрами заключается в том, что с неназванными параметрами вам придется позаботиться о порядке, в котором они будут привязаны к запросу.
Особенно в вашем примере неназванные параметры подходят очень хорошо, так как это облегчает вызов функции.
Обратите внимание, что вам не нужно вызывать return $this;
в методе конструктора.
В вашем случае это не имеет значения.
Хотя нет технической разницы (поскольку PDO просто заменит именные заполнители на вопросительные знаки внутри), есть проблема с удобством использования
Для функции sprintf-like вопросительные знаки выглядят намного лучше. Поскольку они позволят вам использовать действительно стиль sprintf (не знаю, почему вы создаете целый класс для запроса):
$query = new Query("SELECT * FROM t WHERE a=? AND b=?", $ida, $idb);
в то время как с именем он будет намного более подробным