Работа с БД

Плейсхолдеры для переменных

Плейсхолдер (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();

}

 

© Автор и разработчик Михаил Шершнёв, 2006–2021
E-mail: support@bwframework.ru