Работа с БД
Плейсхолдеры для переменных
Плейсхолдер (placeholder) означает заменитель, вместо специальных маркеров будут подставленны данные из переданных переменных и правильным образом экранированы.
Плейсхолдер | Тип данных PHP к которому будет приведено переданное значение | Описание |
---|---|---|
? | string | Строка или бинарная-строка (текст, файл, картинка). Можно передать массив, тогда он будет сериализован. |
?a | Cписковый массив (все переданные значения экранируются). | |
?l | Ассоциативный массив (ключ - имя поля) | |
?_ | префиксный (для названия таблиц), подставляется автоматически из константы TP. | |
?d или ?i | integer | целочисленный |
?f | float | вещественный (дробный) |
?t | имя таблицы | |
?o | оригинал значения, вставляется как есть, не экранируется. |
Примеры
Получить одну запись.
Метод get_record() или select_row(), возвращает массив с полями записи или null, если запись не найдена.
$sql = 'SELECT * FROM table WHERE id = ?d';
$row = app::$db->select_row( $sql, $record_id );
// или
$row = app::$db->get_record( $sql, $record );
if( $row !== null ){
print_r( $row );
}
Получить более одной записи.
Метод get_records() возвращает массив с записями, где каждый элемент, массив с полями записи. Если в выборке нет записей, то будет возвращён пустой массив, поэтому переменную $records можно сразу передать в цикл, без предварительной проверки на тип переменной (массив это или нет).
$sql = 'SELECT * FROM catalog c LEFT JOIN categories cs ON c.category_id = cs.id WHERE cs.name = ?';
$records = app::$db->get_records( $sql, 'утюги' );
foreach( $records as $record ){
print_r( $record );
}
Второй похожий метод select(), возвращает массив с записями или null, если в выборке нет записей. Перед использованием в цикле, необходимо добавлять проверку.
$sql = 'SELECT * FROM catalog c LEFT JOIN categories cs ON c.category_id = cs.id WHERE cs.name = ?';
$records = app::$db->select( $sql, 'утюги' );
if( is_array( $records ) == true ){
foreach( $records as $record ){
print_r( $record );
}
}
Получить записи в постраничном режиме.
$ext_pn = get_int('pn', 1);
$limit = 20;
$sql_where = [];
$sql_where[] = app::$db->prepare_sql( 'cs.name = ?', 'утюги' );
$total_records = 0;
$sql = 'SELECT COUNT(*) AS `cnt` FROM catalog c';
$sql.= ' LEFT JOIN categories cs ON c.category_id = cs.id';
$sql.= ' ' . app::$db->prepare_where( $sql_where );
$row = app::$db->select_row( $sql );
if( $row != null ) {
$total_records = $row['cnt'];
}
$page_number = get_page_number( $total_records, $limit, $ext_pn );
$sql = 'SELECT c.* FROM catalog c LEFT JOIN categories cs ON c.category_id = cs.id';
$sql.= ' ' . app::$db->prepare_where( $sql_where );
$sql.= ' ' . app::$db->prepare_order('c.name ASC');
$sql.= ' ' . app::$db->prepare_limit( $page_number, $limit );
$records = app::$db->get_records( $sql );
foreach( $records as $record ){
print_r( $record );
}
Выборка с кэшированием.
Вставка одной записи.
$ins_data = [];
$ins_data['name'] = 'Вася';
$ins_data['age'] = 21;
$sql = 'INSERT INTO users SET ?l, ip = ?';
$user_id = app::$db->insert( $sql, $ins_data, $_SERVER['REMOTE_ADDR'] );
// или
$sql = 'INSERT INTO users SET name = ?, age = ?d, ip = ?';
$user_id = app::$db->insert( $sql, 'Вася', 21, $_SERVER['REMOTE_ADDR'] );
if( $user_id > 0 ){
// Запись сохранена.
}
else {
// Не удалось создать запись, метод вернул 0.
}
Вставка множества записей.
$data = [];
$data[] = [
'name' => 'Вася',
'age' => 21,
];
$data[] = [
'name' => 'Петя',
'age' => 18,
];
$fields = [
'name' => '?',
'age' => '?d',
];
app::$db->insert_data( 'users', $data, $fields );
Изменение записи.
Метод query() возвращает тоже самое, что возвращает нативная функция mysqli_query(), но на неудачу реагирует исключением, чтобы ошибка была заметнее.
$upd_data = [];
$upd_data['phone'] = '+7 922 222 2222';
$upd_data['name'] = 'Петя';
// Если запрос по причине ошибок не выполнен, функция порождает исключение.
$sql = 'UPDATE users SET ?l WHERE id = ?d';
app::$db->query( $sql, $upd_data, 52 );
// Получить количество изменённых записей.
echo app::$db->affected_rows();
Удаление записей.
$sql = 'DELETE FROM users WHERE id = ?d';
app::$db->query( $sql, $user_id );
// Получить количество удалённых записей.
echo app::$db->affected_rows();
Использование транзакций.
Использовать транзакции необходимо всегда, когда выполняется два и более связанных запросов на изменение (INSERT, UPDATE, DELETE, ALTER). Через механизм транзакций осуществляется атомарность связанных запросов и повышается надёжность приложения.
// Запустить механизм транзакций.
app::$db->start();
try {
$balance = 1000.30;
$sql = 'INSERT INTO users SET name = ?';
$user_id = app::$db->insert( $sql, 'Вася');
if( $user_id > 0 ){
// Методы insert() и query(), если не удаётся выполнить запросы, вызовут исключение.
// В принципе нет необходимости проверять, что будет в $wallet_id, ноль или код отличный от нуля.
// Программист знает, что всегда будет возвращён код отличный от нуля, так как задана колонка AUTO_INCREMENT.
$sql = 'INSERT INTO account SET user_id = ?d, balance = ?f';
$wallet_id = app::$db->insert( $sql, $user_id, $balance );
$sql = 'UPDATE users SET wallet_id = ?d WHERE id = ?d';
app::$db->query( $sql, $wallet_id, $user_id );
}
else {
throw new Exception('Error');
}
// Всё отлично, запросы отработали как нужно, закончить транзакцию (закоммитить),
// то есть все изменения теперь появятся в базе.
app::$db->commit();
}
catch ( Exception $e ){
// Откатить все выполненные запросы.
app::$db->rollback();
}