Ну, во-первых, я бы дал обобщенный ответ, который, вероятно, помог бы другим людям наткнуться на этот вопрос, а затем пересмотрел бы ваш конкретный случай.
Я задал себе тот же вопрос давным-давно и в конце концовпришел к набору решений, которые облегчают операции с базой данных с помощью mysqli.
Mysqli connection
У меня есть сомнения по поводу сохранения кода подключения в функции.Он просит, чтобы его неправильно использовали.Соединение с одной базой данных должно быть строго установлено один раз во время одного экземпляра HTTP-запроса / php.но цель функции вызываться несколько раз.Вместо этого было бы лучше поместить код подключения в файл, а затем просто включить этот файл в свой код в одном месте.
У меня есть канонический код подключения mysqli , которыйрешает множество проблем еще до того, как они появятся.Итак, вместо function db_connect()
давайте создадим файл с именем mysqli.php
и поместим туда следующий код
<?php
$host = '127.0.0.1';
$db = 'test';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$conn = new mysqli($host, $user, $pass, $db);
$conn->set_charset($charset);
} catch (\mysqli_sql_exception $e) {
throw new \mysqli_sql_exception($e->getMessage(), $e->getCode());
}
unset($host, $db, $user, $pass, $charset); // we don't need them anymore
Среди других решений переведет ошибки mysql в исключения PHP ,в основном все, что вам нужно для того, чтобы иметь дело с ошибками.
Выполнение подготовленных запросов
Следующая проблема - довольно сложный код, необходимый для подготовленных запросов в mysqli.Чтобы справиться с этим, я написал вспомогательную функцию mysqli , которая значительно облегчает процесс.
обратите внимание, что, хотя ваш текущий подход с mysqli_real_escape_string()
технически *1030* безопасен, он, тем не менее, осуждается, поскольку он является предметом человеческих ошибок всех видов.Лучше придерживаться подготовленных операторов для всех запросов, которые включают переменную PHP в качестве входных данных.
Поэтому следующим решением будет вспомогательная функция, подобная этой
function prepared_query($mysqli, $sql, $params = [], $types = "")
{
if (!$params) {
return $mysqli->query($sql);
}
$types = $types ?: str_repeat("s", count($params));
$stmt = $mysqli->prepare($sql);
$stmt->bind_param($types, ...$params);
$stmt->execute();
return $stmt->get_result();
}
, и вы получите инструмент, который сделает подготовленные операторы такими же гладкими, как и обычные запросы
Вызов хранимых процедур с помощью mysqli
Хранимые процедуры не просты из-за причуды: каждый вызов возвращает более одного набора результатов , и поэтому нам нужно их циклически обойти.Мы не можем избежать этого, но, по крайней мере, мы можем автоматизировать и этот процесс.Мы можем написать функцию, которая инкапсулирует весь набор результатов jiggery-pokery.
function prepared_call($mysqli, $sql, $params = [], $types = ""): array
{
$resource = prepared_query($mysqli, $sql, $params, $types);
$data = $resource->fetch_all(MYSQLI_ASSOC);
while(mysqli_more_results($mysqli)) mysqli_next_result($mysqli);
return $data;
}
Специальная функция для вызова PK
И, наконец, мы можем переписать вашу select_pk()
функцию
function select_pk($mysqli, string $pk): array
{
$data = prepared_call($mysqli, "CALL select__pk(?)", $pk);
return $data[0] ?? null;
}
Я не совсем уверен, что нам нужнаисключение здесь:
include 'mysqli.php';
$result = select_pk($mysqli, $pk);
if (!$result) {
/*** do something ***/
}