Это очень хороший вопрос, и у меня есть несколько ответов на него.
Необработанный PHP
Прежде всего, вы можете использовать несколько приемов, чтобы уменьшить многословность, например, опуская предложение fields взапрос (и добавление значений по умолчанию в предложении значений для пропущенных полей) и использование позиционных заполнителей:
$sql = 'INSERT INTO tasks VALUES(null, ?, ?, ?)';
$this->pdo->prepare($sql)->execute([$taskName, $startDate, $completedDate]);
Я называю их хитростями, потому что они не всегда применимы.
Обратите внимание, чтоВы должны предоставить значение для всех столбцов в таблице. Это может быть просто значение null
или, чтобы сделать его эквивалентным для пропущенного поля на 100%, вы можете указать его как DEFAULT(field_name)
, чтобы оно вставляло значение по умолчанию, определенное в определении таблицы.
Aвспомогательная функция
Следующим уровнем будет создание вспомогательной функции для вставок. При этом необходимо остро осознавать SQL-инъекцию через имена полей .
Следовательно, такая вспомогательная функция должна иметь собственную вспомогательную функцию:
function escape_mysql_identifier($field){
return "`".str_replace("`", "``", $field)."`";
}
Имея такую функцию, мы можем создать вспомогательную функцию, которая принимает имя поля и массив с полями
function prepared_insert($conn, $table, $data) {
$keys = array_keys($data);
$keys = array_map('escape_mysql_identifier', $keys);
$fields = implode(",", $keys);
$table = escape_mysql_identifier($table);
$placeholders = str_repeat('?,', count($keys) - 1) . '?';
$sql = "INSERT INTO $table ($fields) VALUES ($placeholders)";
$conn->prepare($sql)->execute(array_values($data));
}
Я намеренно не использую именованные заполнители здесь, потому что это делает код короче, могут быть символы, запрещенные в именах заполнителей, в то время как они полностью допустимы для имен столбцов, например, пробела или тире;а также потому, что нам, как правило, все равно, как это работает внутри.
Теперь ваш код вставки станет
prepared_insert($this->pdo, 'tasks',[
'task_name' => $taskName,
'start_date' => $startDate,
'completed_date' => $completedDate,
]);
с таким количеством удаленных повторений
Ребенок ORM
Однако вышеприведенное решение мне тоже не нравится, в нем есть некоторые причуды.
Чтобы удовлетворить потребность в автоматизации, я бы предпочел создать простой ORM. Не пугайтесь этого термина, он не так чудовищен, как некоторые представляют его. У меня есть полный рабочий пример , опубликованный недавно, так что вы можете использовать его и для своего случая, особенно если вы уже используете ООП.
Просто добавьте insert()
метод
public function insert()
{
$fields = '`'.implode("`,`", $this->_fields).'`';
$placeholders = str_repeat('?,', count($this->_fields) - 1) . '?';
$data = [];
foreach($this->_fields as $key)
{
$data[] = $this->{$key};
}
$sql = "INSERT INTO `{$this->_table}` ($fields) VALUES ($placeholders)";
$this->_db->prepare($sql)->execute($data);
}
После этого вам придется подготовить свой класс,
class Task extends BaseDataMapper
{
protected $_table = "tasks";
protected $_fields = ['task_name', 'start_date', 'completed_date'];
}
, а затем - вся магия происходит здесь! - вам вообще не придется писать код вставки! Вместо этого просто создайте новый экземпляр вашего класса, присвойте значения его свойствам, а затем просто вызовите метод insert()
:
include 'pdo.php';
$task = new Task($pdo);
$task->task_name = $taskName;
$task->start_date = $startDate;
$task->completed_date = $completedDate;
$user->insert();