Поэтому у меня есть этот неполный метод сохранения объекта в базе данных:
public function save() { $variables = get_object_vars($this); $attributes = []; foreach ($variables as $variable => $value) { $attributes[] = $value; } $variableString = implode(", ", $attributes); foreach ($variables as $variable => $value) { $attributes[] = ":" . $value; } $valueString = implode(", ", $attributes); $sql = "INSERT INTO products (" . $variableString . ") VALUES (" . $valueString . ")"; $query = $this->pdo->prepare($sql); // ... }
Как связать такие значения с помощью массивов, которые я уже создал?
$query->execute(array( ':username' => $username, ':email' => $email, ':password' => $password ));
Вот как я это сделаю:
// This gets an associative array $variables = get_object_vars($this); // Init $columns = []; $placeholders = []; $bindings = []; // Loop through variables and build arrays foreach ($variables as $column => $value) { $columns[] = $column; $placeholder = ':' . $column; $placeholders[] = $placeholder; $bindings[$placeholder] = $value; } // Create strings $columnString = implode(',', $columns); $placeholderString = implode(',', $placeholders); // Prepare query $sql = "INSERT INTO products (" . $columnString . ") VALUES (" . $placeholderString . ")"; $query = $this->pdo->prepare($sql); // Execute query $query->execute($bindings);
Вы в основном готовите части, которые вам нужны заранее, а затем передавайте их.
Я должен упомянуть, что это может быть хрупким способом сделать это из-за того, что он предполагает, что атрибуты вашего класса всегда находятся в вашей таблице базы данных. Он в основном принимает один $myModel->non_column = 123;
где-нибудь, где нужно пропустить и разорвать ваш запрос.
Похоже, вы пытаетесь создать свою собственную реализацию Active Record, возможно? Может захотеть посмотреть, как это делают некоторые из крупных игроков, или просто использовать их.
Попробуйте следующее, чтобы иметь $ placeholders и $ columnNames для построения вашего запроса, а также атрибуты $, которые должны быть переданы вашему $query->execute()
public function save() { $variables = get_object_vars($this); $attributes = []; foreach ($variables as $key => $value) { $attributes[':' . $key] = $value; } $keys = array_keys($attributes); $placeholders = implode(", ", $keys); $columnNames = str_replace(':', '', $placeholders ); $sql = "INSERT INTO products (" . $columnNames . ") VALUES (" . $placeholders . ")"; $query = $this->pdo->prepare($sql); // ... }
другим подходом было бы построить два массива: один для заполнителей и один для значений, а затем использовать метод array_combine для достижения тех же $ атрибутов. однако этому методу не хватало имен столбцов, и вы должны были убедиться, что ваш объект предоставляет все столбцы таблиц в правильном порядке, то есть $sql = "INSERT INTO products VALUES (" . $placeholders . ")";
На самом деле у вас это есть. Фактически, массив $variables
– это то, что вы ищете: просто отправьте его в execute()
.
Кроме того, все вышеперечисленные решения слишком многословны для моего вкуса. Чтобы создать пару простых строк, дело не в этом:
$variables = get_object_vars($this); $columns = array_keys($variables); $columnString = '`'.implode('`,`', $columns).'`'; $placeholderString = ':'.implode(',:', $columns); $sql = "INSERT INTO products ($columnString) VALUES ($placeholderString)"; $this->pdo->prepare($sql)->execute($variables);
Обратите внимание, что для динамически построенного запроса использование разделителей вокруг идентификаторов является обязательным, так как вы никогда не можете определить, какое свойство оказывается ключевым словом mysql.