Как изменить MySQL на MySQL?
Основываясь на этом коде ниже, который я использую для обычного mysql, как я могу преобразовать его в mysqli?
Это так же просто, как изменить ** mysql _query ($ sql); в mysqli _query ($ sql);? **
<?PHP
//in my header file that is included on every page I have this
$DB["dbName"] = "emails";
$DB["host"] = "localhost";
$DB["user"] = "root";
$DB["pass"] = "";
$link = mysql_connect($DB['host'], $DB['user'], $DB['pass']) or die("<center>An Internal Error has Occured. Please report following error to the webmaster.<br><br>".mysql_error()."'</center>");
mysql_select_db($DB['dbName']);
// end header connection part
// function from a functions file that I run a mysql query through in any page.
function executeQuery($sql) {
$result = mysql_query($sql);
if (mysql_error()) {
$error = '<BR><center><font size="+1" face="arial" color="red">An Internal Error has Occured.<BR> The error has been recorded for review</font></center><br>';
if ($_SESSION['auto_id'] == 1) {
$sql_formatted = highlight_string(stripslashes($sql), true);
$error .= '<b>The MySQL Syntax Used</b><br>' . $sql_formatted . '<br><br><b>The MySQL Error Returned</b><br>' . mysql_error();
}
die($error);
}
return $result;
}
// example query ran on anypage of the site using executeQuery function
$sql='SELECT auto_id FROM friend_reg_user WHERE auto_id=' .$info['auto_id'];
$result_member=executequery($sql);
if($line_member=mysql_fetch_array($result_member)){
extract($line_member);
} else {
header("location: index.php");
exit;
}
?>
16 ответов
Первое, что нужно сделать, вероятно, будет заменить каждый mysql_*
вызов функции с ее эквивалентом mysqli_*
По крайней мере, если вы хотите использовать процедурный API - что было бы проще, учитывая, что у вас уже есть некоторый код, основанный на MySQL API, который является процедурным.
Чтобы помочь с этим, Краткий обзор функций расширения MySQLi определенно окажется полезным.
Например:
mysql_connect
будет заменен наmysqli_connect
mysql_error
будет заменен наmysqli_error
и / илиmysqli_connect_error
в зависимости от контекстаmysql_query
будет заменен наmysqli_query
- и так далее
Обратите внимание, что для некоторых функций вам может потребоваться тщательно проверить параметры: может быть, есть некоторые различия здесь и там - но не так много, я бы сказал: и mysql, и mysqli основаны на одной и той же библиотеке (libmysql; at минимум для PHP <= 5.2)
Например:
- с MySQL, вы должны использовать
mysql_select_db
после подключения, чтобы указать, к какой базе данных вы хотите сделать ваши запросы - mysqli, с другой стороны, позволяет вам указать это имя базы данных в качестве четвертого параметра
mysqli_connect
, - Тем не менее, есть также
mysqli_select_db
функция, которую вы можете использовать, если хотите.
Как только вы закончите с этим, попробуйте выполнить новую версию вашего скрипта... и проверьте, все ли работает; если нет... Время для поиска ошибок;-)
(Я понимаю, что это старый, но все еще подходит...)
Если вы замените mysql_*
с mysqli_*
затем имейте в виду, что весь груз mysqli_*
функциям нужна ссылка на базу данных.
Например:
mysql_query($query)
становится
mysqli_query($link, $query)
Т.е. требуется много проверок.
Главное руководство по обновлению mysql_*
функции к MySQLi API
Причиной нового расширения mysqli стало использование новых функций, доступных в системах MySQL версий 4.1.3 и новее. При изменении существующего кода с mysql_*
Для mysqli API вы должны воспользоваться этими улучшениями, иначе ваши усилия по обновлению могут оказаться напрасными.
Расширение mysqli имеет ряд преимуществ, ключевые улучшения по сравнению с расширением mysql:
- Объектно-ориентированный интерфейс
- Поддержка подготовленных заявлений
- Расширенные возможности отладки
При обновлении с mysql_*
функции MySQLi, важно принять во внимание эти функции, а также некоторые изменения в способе использования этого API.
1. Объектно-ориентированный интерфейс и процедурные функции.
Новый объектно-ориентированный интерфейс mysqli является большим улучшением по сравнению со старыми функциями и может сделать ваш код чище и менее восприимчивым к опечаткам. Существует также процедурная версия этого API, но его использование не рекомендуется, так как это приводит к менее читаемому коду, который более подвержен ошибкам.
Чтобы открыть новое соединение с базой данных с MySQLi, вам нужно создать новый экземпляр класса MySQLi.
$mysqli = new \mysqli($host, $user, $password, $dbName);
$mysqli->set_charset('utf8mb4');
Используя процедурный стиль, это выглядело бы так:
$mysqli = mysqli_connect($host, $user, $password, $dbName);
mysqli_set_charset($mysqli, 'utf8mb4');
Имейте в виду, что только первые 3 параметра такие же, как в mysql_connect
, Тот же код в старом API будет:
$link = mysql_connect($host, $user, $password);
mysql_select_db($dbName, $link);
mysql_query('SET NAMES utf8');
Если ваш PHP-код основывался на неявном соединении с параметрами по умолчанию, определенными в php.ini, теперь вам нужно открыть соединение MySQLi, передав параметры в вашем коде, а затем предоставить ссылку на соединение со всеми процедурными функциями или использовать стиль ООП.
Для получения дополнительной информации см. Статью: Как правильно подключиться с помощью mysqli
2. Поддержка подготовленных заявлений
Это большой. В MySQL добавлена поддержка встроенных операторов в MySQL 4.1 (2004). Подготовленные операторы - лучший способ предотвратить внедрение SQL. Было логично, что в PHP была добавлена поддержка нативно подготовленных операторов. Подготовленные операторы следует использовать всякий раз, когда необходимо передать данные вместе с оператором SQL (т. Е. WHERE
, INSERT
или же UPDATE
обычные случаи использования).
Старый MySQL API имел функцию для экранирования строк, используемых в SQL, называемую mysql_real_escape_string
, но он никогда не был предназначен для защиты от SQL-инъекций и, естественно, не должен использоваться для этой цели.
Новый MySQLi API предлагает функцию замены mysqli_real_escape_string
для обратной совместимости, которая страдает теми же проблемами, что и старая, и поэтому не должна использоваться, если готовые операторы недоступны.
Старый способ mysql_*:
$login = mysql_real_escape_string($_POST['login']);
$result = mysql_query("SELECT * FROM users WHERE user='$login'");
Подготовленный способ постановки:
$stmt = $mysqli->prepare('SELECT * FROM users WHERE user=?');
$stmt->bind_param('s', $_POST['login']);
$stmt->execute();
$result = $stmt->get_result();
Подготовленные заявления в MySQLi могут показаться немного неприятными для начинающих. Если вы начинаете новый проект, тогда решение об использовании более мощного и простого API PDO может быть хорошей идеей.
3. Расширенные возможности отладки
Некоторые разработчики PHP старой школы привыкли проверять ошибки SQL вручную и отображать их непосредственно в браузере в качестве средства отладки. Однако такая практика оказалась не только громоздкой, но и угрозой безопасности. К счастью, MySQLi улучшил возможности сообщения об ошибках.
MySQLi может сообщать о любых ошибках, с которыми он сталкивается, как об исключениях PHP. Исключения PHP будут пузыриться в скрипте и, если их не обработать, немедленно прервут его, что означает, что никакое утверждение после ошибочного никогда не будет выполнено. Исключение вызовет фатальную ошибку PHP и будет вести себя как любая ошибка, вызванная ядром PHP, подчиняющимся display_errors
а также log_errors
Настройки. Чтобы включить исключения MySQLi, используйте строку mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT)
и вставьте его прямо перед открытием соединения с БД.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new \mysqli($host, $user, $password, $dbName);
$mysqli->set_charset('utf8mb4');
Если вы привыкли писать такой код:
$result = mysql_query('SELECT * WHERE 1=1');
if (!$result) {
die('Invalid query: ' . mysql_error());
}
или же
$result = mysql_query('SELECT * WHERE 1=1') or die(mysql_error());
вам больше не нужно die()
в вашем коде.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new \mysqli($host, $user, $password, $dbName);
$mysqli->set_charset('utf8mb4');
$result = $mysqli->query('SELECT * FROM non_existent_table');
// The following line will never be executed due to the mysqli_sql_exception being thrown above
foreach ($result as $row) {
// ...
}
Если по какой-то причине вы не можете использовать исключения, MySQLi имеет эквивалентные функции для поиска ошибок. Вы можете использовать mysqli_connect_error()
проверить наличие ошибок подключения и mysqli_error($mysqli)
за любые другие ошибки. Обратите внимание на обязательный аргумент в mysqli_error($mysqli)
или альтернативно придерживаться стиля ООП и использовать $mysqli->error
,
$result = $mysqli->query('SELECT * FROM non_existent_table') or trigger_error($mysqli->error, E_USER_ERROR);
Смотрите эти сообщения для более подробного объяснения:
MySQL или умереть, он должен умереть?
Как получить информацию об ошибках MySQLi в разных средах?
4. Другие изменения
К сожалению, не каждая функция из mysql_*
имеет свой аналог в MySQLi только с добавленным "i" в имени и связи в качестве первого параметра. Вот список некоторых из них:
mysql_client_encoding()
был замененmysqli_character_set_name($mysqli)
mysql_create_db
не имеет аналога. Используйте подготовленные заявления илиmysqli_query
вместоmysql_drop_db
не имеет аналога. Используйте подготовленные заявления илиmysqli_query
вместоmysql_db_name
&mysql_list_dbs
поддержка была отброшена в пользу SQLSHOW DATABASES
mysql_list_tables
поддержка была отброшена в пользу SQLSHOW TABLES FROM dbname
mysql_list_fields
поддержка была отброшена в пользу SQLSHOW COLUMNS FROM sometable
mysql_db_query
-> использоватьmysqli_select_db()
тогда запрос или укажите имя БД в запросеmysql_fetch_field($result, 5)
-> второй параметр (смещение) отсутствует вmysqli_fetch_field
, Вы можете использоватьmysqli_fetch_field_direct
имея в виду разные результаты, возвращенныеmysql_field_flags
,mysql_field_len
,mysql_field_name
,mysql_field_table
&mysql_field_type
-> был заменен наmysqli_fetch_field_direct
mysql_list_processes
был удален. Если вам нужен идентификатор потока, используйтеmysqli_thread_id
mysql_pconnect
был заменен наmysqli_connect()
с участиемp:
префикс хостаmysql_result
-> использоватьmysqli_data_seek()
в сочетании сmysqli_field_seek()
а такжеmysqli_fetch_field()
mysql_tablename
поддержка была отброшена в пользу SQLSHOW TABLES
mysql_unbuffered_query
был удален. См. Эту статью для получения дополнительной информации Буферизованные и Небуферизованные запросы
Самый простой способ, которым я всегда справляюсь
Где $ con = mysqli_connect ($ serverName, $ dbusername, $ dbpassword);
3 шага замены в следующем порядке
- Все "mysql_select_db (" с "mysqli_select_db ($ con,"
- Все "mysql_query (" с "mysqli_query ($ con," и
- Все "mysql_" с "mysqli_".
Это работает для меня каждый раз
2020+ Ответ
Я создал инструмент под названием Rector, который выполняет мгновенные обновления. Также есть mysql → mysqli set.
Он обрабатывает:
- переименование функции
- постоянное переименование
- переключенные аргументы
изменения вызовов функций, отличных от 1:1, например
$data = mysql_db_name($result, $row);
↓
mysqli_data_seek($result, $row); $fetch = mysql_fetch_row($result); $data = $fetch[0];
Просто используйте это в своем коде:
composer require rector/rector --dev
vendor/bin/rector process src --set mysql-to-mysqli
Я уже запускал его на 2 больших PHP-проектах, и он отлично работает.
В случае больших проектов, нужно изменить много файлов, а также, если предыдущая версия PHP была 5.6, а новая - 7.1, вы можете создать новый файл sql.php и включить его в заголовок, или где-нибудь еще использовать. время и нуждается в соединении sql. Например:
//local
$sql_host = "localhost";
$sql_username = "root";
$sql_password = "";
$sql_database = "db";
$mysqli = new mysqli($sql_host , $sql_username , $sql_password , $sql_database );
/* check connection */
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
// /* change character set to utf8 */
if (!$mysqli->set_charset("utf8")) {
printf("Error loading character set utf8: %s\n", $mysqli->error);
exit();
} else {
// printf("Current character set: %s\n", $mysqli->character_set_name());
}
if (!function_exists('mysql_real_escape_string')) {
function mysql_real_escape_string($string){
global $mysqli;
if($string){
// $mysqli = new mysqli($sql_host , $sql_username , $sql_password , $sql_database );
$newString = $mysqli->real_escape_string($string);
return $newString;
}
}
}
// $mysqli->close();
$conn = null;
if (!function_exists('mysql_query')) {
function mysql_query($query) {
global $mysqli;
// echo "DAAAAA";
if($query) {
$result = $mysqli->query($query);
return $result;
}
}
}
else {
$conn=mysql_connect($sql_host,$sql_username, $sql_password);
mysql_set_charset("utf8", $conn);
mysql_select_db($sql_database);
}
if (!function_exists('mysql_fetch_array')) {
function mysql_fetch_array($result){
if($result){
$row = $result->fetch_assoc();
return $row;
}
}
}
if (!function_exists('mysql_num_rows')) {
function mysql_num_rows($result){
if($result){
$row_cnt = $result->num_rows;;
return $row_cnt;
}
}
}
if (!function_exists('mysql_free_result')) {
function mysql_free_result($result){
if($result){
global $mysqli;
$result->free();
}
}
}
if (!function_exists('mysql_data_seek')) {
function mysql_data_seek($result, $offset){
if($result){
global $mysqli;
return $result->data_seek($offset);
}
}
}
if (!function_exists('mysql_close')) {
function mysql_close(){
global $mysqli;
return $mysqli->close();
}
}
if (!function_exists('mysql_insert_id')) {
function mysql_insert_id(){
global $mysqli;
$lastInsertId = $mysqli->insert_id;
return $lastInsertId;
}
}
if (!function_exists('mysql_error')) {
function mysql_error(){
global $mysqli;
$error = $mysqli->error;
return $error;
}
}
Я бы рекомендовал использовать PDO для доступа к SQL.
Тогда это всего лишь случай изменения драйвера и обеспечения работы SQL на новом бэкэнде. Теоретически. Перенос данных - это другая проблема.
Абстрактный доступ к базе данных отличный.
Вот полный урок, как сделать это правильно и быстро. Я использовал его после обновления хостинга для своих клиентов с версии 5.4 (OMG!!!) до версии 7.x PHP.
1. Определение соединения
Прежде всего, вам нужно поставить соединение с новой переменной $link
или же $con
или что хочешь.
пример
Измените соединение с:
@mysql_connect($host, $username, $password) or die("Error message...");
@mysql_select_db($db);
или же
@mysql_connect($host, $username, $password, $db) or die("Error message...");
чтобы:
$con = mysqli_connect($host, $username, $password, $db) or die("Error message...");
2. mysql_ * модификация
В Notepad++ я использую "Найти в файлах" (Ctrl + Shift + f):
в следующем порядке я выбираю "Заменить в файлах":
mysql_query (-> mysqli_query ($ con,
mysql_error () -> mysqli_error ($ con)
mysql_close () -> mysqli_close ($ con)
mysql_ -> mysqli_
3. корректировки
если вы получаете ошибки, это может быть потому, что ваш $ con не доступен из ваших функций.
Вам нужно добавить global $con;
во всех ваших функциях, например:
function my_function(...) {
global $con;
...
}
Надеюсь, поможет.
Если у вас есть много файлов для изменения в ваших проектах, вы можете создавать функции с такими же именами, как и функции mysql, а в функциях конвертировать, как этот код:
$sql_host = "your host";
$sql_username = "username";
$sql_password = "password";
$sql_database = "database";
$mysqli = new mysqli($sql_host , $sql_username , $sql_password , $sql_database );
/* check connection */
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
function mysql_query($query){
$result = $mysqli->query($query);
return $result;
}
function mysql_fetch_array($result){
if($result){
$row = $result->fetch_assoc();
return $row;
}
}
function mysql_num_rows($result){
if($result){
$row_cnt = $result->num_rows;;
return $row_cnt;
}
}
Я только что создал функцию с такими же именами для преобразования и перезаписи на новый php7:
$host = "your host";
$un = "username";
$pw = "password";
$db = "database";
$MYSQLI_CONNECT = mysqli_connect($host, $un, $pw, $db);
function mysql_query($q) {
global $MYSQLI_CONNECT;
return mysqli_query($MYSQLI_CONNECT,$q);
}
function mysql_fetch_assoc($q) {
return mysqli_fetch_assoc($q);
}
function mysql_fetch_array($q){
return mysqli_fetch_array($q , MYSQLI_BOTH);
}
function mysql_num_rows($q){
return mysqli_num_rows($q);
}
function mysql_insert_id() {
global $MYSQLI_CONNECT;
return mysqli_insert_id($MYSQLI_CONNECT);
}
function mysql_real_escape_string($q) {
global $MYSQLI_CONNECT;
return mysqli_real_escape_string($MYSQLI_CONNECT,$q);
}
У меня работает, надеюсь, у всех сработает, если ошибаюсь, поправьте.
Хотя этой теме уже десять лет, мне все еще часто приходится "исправлять" существующие приложения, основанные на mysql
extension - исходные программисты были слишком ленивы, чтобы реорганизовать весь свой код, и просто сказали клиентам, чтобы они использовали последнюю доступную версию PHP 5.6.
PHP 5.6 официально объявлен устаревшим; другими словами, у разработчиков было десятилетие, чтобы избавиться от своей зависимости отmysql
и перейти к PDO
(или, ну, mysqli
...). Но... изменение такого количества устаревшего кода обходится дорого, и не каждый менеджер готов платить за бесчисленные часы, чтобы "исправить" проекты с десятками тысяч строк.
Я искал много решений, и в моем случае я часто использовал решение, представленное @esty-shlomovitz, но тем временем я нашел кое-что еще лучше:
https://www.phpclasses.org/package/9199-PHP-Replace-mysql-functions-using-the-mysqli-extension.html
(вам необходимо зарегистрироваться, чтобы скачать его, но это займет всего минуту)
Это всего лишь два файла, которые служат заменой для всего mysql
расширение и очень умно эмулирует почти все (используя mysqli
), не беспокоясь об этом. Конечно, это не идеальное решение, но, скорее всего, оно сработает в 99% случаев.
Кроме того, здесь можно найти хорошее руководство по работе с рутинной миграцией (перечисление многих распространенных ошибок при миграции): https://www.phpclasses.org/blog/package/9199/post/3-Smoothly-Migrate-your-PHP-Code-using-the-Old-MySQL-extension-to-MySQLi.html
(если вы читаете это в 2030 году, а веб-сайт PHPclasses не работает, что ж, вы всегда можете попробовать archive.org:-)
Обновление: @crashwap отметил в комментариях ниже, что вы также можете получить тот же код непосредственно из GitHub. Спасибо за подсказку, @crashwap:-)
Краткая версия преобразования MySQL в MySQL
mysql_connect ---> mysqli_connect
mysql_select_db ---> mysqli_select_db
mysql_error ---> mysqli_connect_error()
mysql_query ---> mysqli_query
mysql_fetch_assoc ---> mysqli_fetch_assoc
Вы можете включить этот класс php для преобразования
mysql_
к
mysqli_
автоматически, просто включив файл.
Вы можете выполнить массовый поиск и замену, используя notepad++, для меня это сработало:
Найти: mysql_
Заменить: mysqli_
Найти: _query(
Заменить: _query($conn,
Необходимо изменить следующее, но это зависит от того, как вы подключаетесь...
Обновите строку подключения в config.php следующим образом:
$conn = mysqli_connect($db_host, $db_username, $db_password, $db_name) or die("Unable to Connect");
Надеюсь это поможет.
Мой простой сценарий оболочки, чтобы изменить mysql на mysqli во всех файлах php в каталоге:
for I in *.php
do
cat $I | sed s/'mysql_select_db('/'mysqli_select_db($link,'/ |
sed s/'mysql_query('/'mysqli_query($link,'/|
sed s/mysql_/mysqli_/ > tmpf;
mv tmpf $I;
done
аналогично ответу dhw, но вам не нужно беспокоиться о том, чтобы установить ссылку как глобальную во всех функциях, потому что это довольно сложно:
просто используйте этот код в своем файле конфигурации:
$sv_connection = mysqli_connect($dbhost, $dbuser, $dbpass, $dbname);
$db_connection = mysqli_select_db ($sv_connection, $dbname);
mysqli_set_charset($sv_connection, 'utf8'); //optional
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
exit();
}
function mysqljx_query($q){
global $sv_connection;
return mysqli_query($sv_connection, $q);
}
function mysqljx_fetch_array($r){
return mysqli_fetch_array($r);
}
function mysqljx_fetch_assoc($r){
return mysqli_fetch_assoc($r);
}
function mysqljx_num_rows($r){
return mysqli_num_rows($r);
}
function mysqljx_insert_id(){
global $sv_connection;
return mysqli_insert_id($sv_connection);
}
function mysqljx_real_escape_string($string){
global $sv_connection;
return mysqli_real_escape_string($sv_connection, $string);
}
-Теперь выполните поиск файлов php, содержащих "mysql_" (для этого я использовал total commander - Alt + F7, поиск "* .php", поиск текста "mysql_", начало поиска, передача в список)
- перетащите их все в Notepad ++, нажмите CTRL + H, найдите, что: «mysql_», замените на «mysqljx_», «Заменить все во всех открытых документах»
если вас беспокоит, что у вас есть другие функции, кроме перечисленных выше, просто замените одну за другой («mysql_query» на «mysqljx_query», затем mysql_fetch_array на «mysqljx_fetch_array» и т. д.), а затем снова выполните поиск «mysql_», и если он все еще там его открытая функция, и вы можете просто добавить ее так же, как и остальные ..
вот оно что