Как изменить 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 поддержка была отброшена в пользу SQL SHOW DATABASES
  • mysql_list_tables поддержка была отброшена в пользу SQL SHOW TABLES FROM dbname
  • mysql_list_fields поддержка была отброшена в пользу SQL SHOW 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 поддержка была отброшена в пользу SQL SHOW TABLES
  • mysql_unbuffered_query был удален. См. Эту статью для получения дополнительной информации Буферизованные и Небуферизованные запросы

Самый простой способ, которым я всегда справляюсь

Где $ con = mysqli_connect ($ serverName, $ dbusername, $ dbpassword);

3 шага замены в следующем порядке

  1. Все "mysql_select_db (" с "mysqli_select_db ($ con,"
  2. Все "mysql_query (" с "mysqli_query ($ con," и
  3. Все "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):

Поиск и замена блокнота ++

в следующем порядке я выбираю "Заменить в файлах":

  1. mysql_query (-> mysqli_query ($ con,

  2. mysql_error () -> mysqli_error ($ con)

  3. mysql_close () -> mysqli_close ($ con)

  4. 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_», и если он все еще там его открытая функция, и вы можете просто добавить ее так же, как и остальные ..

вот оно что

Другие вопросы по тегам