Более эффективный способ привязки большой вставки или обновления?

Хорошо, поэтому я новый для привязки, вот какой-то код, который работает. Я узнал этот формат из учебника, но я думаю, что есть более эффективные способы сделать это. В моем примере есть 4 имени, но на самом деле я буду делать много вложений и обновлений в проекте, в котором работает, у которого будет 20 или около того полей. Мне нравится этот подход для его ясности, но, очевидно, когда ваш разговор на 20 или более полей занимает много недвижимости. Давайте сначала посмотрим на мой код.

Вот функции, которые он использует:

// prepare the statement public function query($query){ $this->stmt = $this->dbh->prepare($query); } public function bind($param, $value, $type = null){ if (is_null($type)) { switch (true) { case is_int($value): $type = PDO::PARAM_INT; break; case is_bool($value): $type = PDO::PARAM_BOOL; break; case is_null($value): $type = PDO::PARAM_NULL; break; default: $type = PDO::PARAM_STR; } } // run the binding process $this->stmt->bindValue($param, $value, $type); } // execute the prepared statement public function execute(){ return $this->stmt->execute(); } 

и теперь фактический код

 $database->query(" INSERT INTO users( user_name, user_password_hash, user_email, user_activation_hash ) VALUES( :user_name, :user_password_hash, :user_email, :user_activation_hash ) "); // bind the values $database->bind(":user_name", "$this->user_name"); $database->bind(":user_password_hash", "$this->user_password_hash"); $database->bind(":user_email", "$this->user_email"); $database->bind(":user_activation_hash", "$this->user_activation_hash"); // execute the statement and insert the values into the database $database->execute(); 

он просто кричит о петле, тем более, что у меня есть привычка вызывать почтовые поля, поля ввода, переменные и заполнители одинакового имени, не уверен, что это хорошо или плохо, но я нахожу его полезным для меня при работе с большие формы, которые я буду.

в любом случае я мог бы сделать что-то вроде этого:

 $placeholder_array = array( "user_name" => "\$this->user_name", "user_password_hash" => "\$this->user_password_hash", "user_email" => "\$this->user_email", "user_activation_hash" => "\$this->user_activation_hash" ); // well use this copy to edit the array keys and keep original for the binding $placeholder_copy = $placeholder_array; // turn the array into a string ie user_name, user_password_hash.... $fields = implode (", ", array_keys($placeholder_array)); // foreach to add : placeholder prefix for binding foreach ($placeholder_copy as $key => $value){ $placeholder_copy [':'.$key] = $value; unset($placeholder_copy[$key]); } // turn the copy array which has prefix :user_name into a string $placeholders = implode (", ", array_keys($placeholder_copy)); $database->query(" INSERT INTO users($fields) VALUES($placeholders) "); // bind the values foreach ($placeholder_copy as $bind_values => $value){ echo '$database->bind("'.$bind_values.'", "'.$value.'");' . "<br />"; } // execute the statement and insert the values into the database $database->execute(); с $placeholder_array = array( "user_name" => "\$this->user_name", "user_password_hash" => "\$this->user_password_hash", "user_email" => "\$this->user_email", "user_activation_hash" => "\$this->user_activation_hash" ); // well use this copy to edit the array keys and keep original for the binding $placeholder_copy = $placeholder_array; // turn the array into a string ie user_name, user_password_hash.... $fields = implode (", ", array_keys($placeholder_array)); // foreach to add : placeholder prefix for binding foreach ($placeholder_copy as $key => $value){ $placeholder_copy [':'.$key] = $value; unset($placeholder_copy[$key]); } // turn the copy array which has prefix :user_name into a string $placeholders = implode (", ", array_keys($placeholder_copy)); $database->query(" INSERT INTO users($fields) VALUES($placeholders) "); // bind the values foreach ($placeholder_copy as $bind_values => $value){ echo '$database->bind("'.$bind_values.'", "'.$value.'");' . "<br />"; } // execute the statement and insert the values into the database $database->execute(); 

я мог бы превратить это в функцию с параметрами для передачи в ассоциативном массиве и именем таблицы, чтобы мой основной код был намного чище.

Теперь представьте, что я собираюсь сделать любое их количество, поскольку проект, над которым работает, включает в себя множество больших форм, отправляющих данные пользователям. Я новичок в PDO и пытаюсь понять его, чтобы, возможно, был более простой способ структурирования этих типов запросов, я посмотрел на google и stackflow, но я действительно не понял, что они делают, поэтому я думал, что сделать мой собственный позволит люди, чтобы объяснить мне лучше, что происходит, я бы предпочел, чтобы это правильно начиналось с моего проекта, а не возвращалось и менялось все позже. Так есть лучший подход или это нормально?

Внимательно оцените любую обратную связь и я рад, что теперь я посоветовал людям советы и сделал переход к PDO.

То, что я делал недавно и продолжаю улучшать, создает вспомогательный класс для упрощения SQL-запросов на основе PDO в моих приложениях.

Давайте отправимся в тур с вашим примером. Вы хотите вставить данные в таблицу пользователя:

 INSERT INTO users( user_name, user_password_hash, user_email, user_activation_hash ) VALUES( :user_name, :user_password_hash, :user_email, :user_activation_hash ) 

Для вставки одной записи мой SQL построен таким образом:

 function myInsertSingle($PDO, $table, $ins_array) { $SQL = "INSERT INTO `".$table."` (".dbFieldList($ins_array) .") VALUES (".dbValuePList($ins_array).")"; 

… продолжил подготовку.

  • $PDO : мое соединение PDO.
  • $table : таблица, в которую я хочу вставить.
  • $ins_array : структурированный массив для вставки данных.

Для вашего примера массив $ins_array будет выглядеть следующим образом:

 $ins_array = array( "user_name" => "your_user", "user_password_hash" => "your_pw_hash", "user_email" => "your@mail.xyz", "user_activation_hash" => "your_other_Hash" ); 

Обратите внимание на сходство с вашим массивом!

Сюда относятся две функции. Первый дает мне список (экранированных) полей.

 function dbFieldList($fields) { $set = ''; foreach ($fields as $field => $item) { $set .= "`".$field."`,"; } return rtrim($set, ','); } 

В основном из приведенного выше примера массива функция возвращает

 `user_name`, `user_password_hash`, `user_email`, `user_activation_hash` 

… который является списком полей, необходимых в INSERT состоянии.

Другой делает что-то подобное для значений.

 function dbValuePList($fields) { $set = ''; foreach ($fields as $field => $item) { $set .= ":".$field.","; } return rtrim($set, ','); } 

Вы догадались, результат выглядит следующим образом:

 :user_name, :user_password_hash, :user_email, :user_activation_hash 

Теперь у вас есть своя инструкция SQL, которую вы можете подготовить. Чтобы связать значения, если я правильно понимаю ваш класс, просто используйте цикл, который выглядит так:

 foreach ($ins_array as $field => $item) { $PDO->bind(':'.$field,$item); } 

Теперь вы можете выполнить инструкцию.

Резюме. В основном с моим подходом один оператор INSERT сводится к следующему:

 $ins_array = array( "user_name" => "your_user", "user_password_hash" => "your_pw_hash", "user_email" => "your@mail.xyz", "user_activation_hash" => "your_other_Hash" ); myInsertSingle($PDO, 'your_table', $ins_array); 

Если это выглядит так же, как и другая часть накладных расходов, имейте в виду, я использую эти функции в других операторах SQL, таких как SELECT, UPDATE, DELETE и т. Д.

Нет, к сожалению, но PDO не помогает в этом вопросе.
Но ваш собственный подход не кажется мне эффективным.

Прежде всего, позвольте мне указать, что ваш набор функций совершенно бесполезен. Я не понимаю такого прямого переписывания функций API. PDO уже делает все это.

С raw PDO вы можете иметь еще более сжатый код:

 $stm = $pdo->prepare("INSERT INTO users VALUES(NULL,?,?,?,?)"); $data = array($this->user_name, $this->user_password_hash, $this->user_email, $this->user_activation_hash ); $stm->execute($data); 

Что касается вашего динамического построения запросов, я нахожу его слишком раздутым, но все еще небезопасным . Некоторые недостатки

  • нет смысла беспокоиться о «названных» заполнителях, поскольку они должны быть удобочитаемыми для человека, но никто не должен их читать здесь. Не говоря уже о том, что PDO будет преобразовывать их обратно в? S перед отправкой в ​​mysql
  • другое возражение против именных заполнителей – в то время как Mysql (а также HTTP) может позволить вам иметь пробел в имени поля в порядке, местозаполнитель с пробелом просто сбой вашего запроса.
  • в этом коде нет реальной выгоды от вашего подхода к равным именам – вы обязаны писать их вручную по десятка раз каждый , заметьте.
  • но если он будет использоваться, у вас нет белого списка, чтобы проверить свой список полей, что может быть большим нарушением безопасности
  • слишком много кода
  • нет поддержки для запроса UPDATE что также может быть очень полезно (если вы используете mysql)
  • когда вы вставляете этот код в функцию, вы соскользнете на те же плохие основания, что и другие, соблазненные возможностью сэкономить вам целые два слова!

Вот мой более ранний подход к делу :

 $allowed = array( "user_name", "user_password_hash", "user_email", "user_activation_hash" ); $sql = "INSERT INTO users SET ".pdoSet($allowed, $values); $stmt = $dbh->prepare($sql); $stmt->execute($values); 

И здесь идет мой нынешний подход , лучший из лучших (хотя реализованный с использованием mysqli, а не PDO), используя пользовательский заполнитель для данных массива:

 $placeholder_array = array( "user_name" => $this->user_name, "user_password_hash" => $this->user_password_hash, "user_email" => $this->user_email, "user_activation_hash" => $this->user_activation_hash ); $db->query("INSERT INTO users SET ?u", $placeholder_array); 

или, в случае прямого соединения между полями формы и столбцами SQL

 $allowed = array( "user_name", "user_password_hash", "user_email", "user_activation_hash" ); $insert = $db->filterArray($_POST,$allowed); $db->query("INSERT INTO users SET ?u", $insert); 

Таким образом, позвольте мне использовать INSERT IGNORE , INSERT DELAYED , INSERT.. ON DUPLICATE UPDATE , UPDATE , UPDATE с подключением и бесчисленные другие параметры, поддерживающие полный язык SQL.