programing

PHP에서 MySQL 데이터베이스 찾기/바꾸기 스크립트 작성

powerit 2023. 7. 2. 21:03
반응형

PHP에서 MySQL 데이터베이스 찾기/바꾸기 스크립트 작성

저는 현재 제 맞춤형 웹사이트를 워드프레스 기반의 CMS로 재개발하는 중입니다.

제가 작업하고 있는 웹사이트는 단순히 제 기존 URL 플러스입니다./dev/,예.http://my.website.com/dev/.

이 웹 사이트를 다음으로 이동합니다.http://my.website.com주말 동안, 그리고 따라서 그것은 모든 언급을 제거할 필요가 있을 것입니다./dev/URL.

제가 하고 싶은 것은 기본적으로 다음을 위한 "찾기 및 대체"입니다./dev내 데이터베이스에.어떤 테이블에 이 값이 있는지 정확히 알 수 있지만, WordPress 설치에 따르면 이러한 필드의 상당 부분이 직렬화된 데이터입니다. 이는 간단합니다.dump>open with notepad++>find & replace깨질 것입니다.

이를 위해 개발한 코드는 다음과 같습니다.

<?php

$look_at[] = array( "table" => "wp_options", "fields" => array( "option_value" ), "id_field" => "option_id" );
$look_at[] = array( "table" => "wp_postmeta", "fields" => array( "meta_value" ), "id_field" => "meta_id" );
$look_at[] = array( "table" => "wp_posts", "fields" => array( "post_content", "guid" ), "id_field" => "ID" );
$look_at[] = array( "table" => "wp_sfmeta", "fields" => array( "meta_value" ), "id_field" => "meta_id" );
$look_at[] = array( "table" => "wp_sfoptions", "fields" => array( "option_value" ), "id_field" => "option_id" );
$look_at[] = array( "table" => "wp_sferrorlog", "fields" => array( "error_text" ), "id_field" => "id" );

for ( $i = 0; $i < sizeof ( $look_at ); $i++ ) {
    foreach( $look_at[$i]["fields"] as $field ) {

        $sql = 'SELECT `' . $field . '`, `' . $look_at[$i]["id_field"] . '` FROM  `' . $look_at[$i]["table"] . '`;';
        $res = mysql_query( $sql );

        while ( $row = mysql_fetch_assoc( $res ) ) {

            $table = $look_at[$i]["table"];
            $id_field = $look_at[$i]["id_field"];
            $old_val = $row[$field];
            $id = $row[$id_field];

            $unserialized_value = @unserialize( $old_val );

            if ( $old_val === 'b:0;' || $unserialized_value !== false )
                $new_val = serialize( str_replace( array( "/dev/", "/dev" ), array( "/", "" ), $unserialized_value ) );
            else
                $new_val = str_replace( array( "/dev/", "/dev" ), array( "/", "" ), $old_val );

            $update_array[] = array( "id_field" => $id_field, "id" => $id, "table" => $table, "key" => $key, "old_val" => $old_val, "new_val" => $new_val );

        }

    }
}

for ( $i = 0; $i < sizeof( $update_array ); $i++ ) {
    if ( $update_array[$i]["old_val"] !== $update_array[$i]["new_val"] )
        $updated_sql .= 'UPDATE ' . $update_array[$i]["table"] . ' SET `' . $update_array[$i]["key"] . '` = \'' . $update_array[$i]["new_val"] . '\' WHERE `' . $update_array[$i]["id_field"] . '` = \'' . $update_array[$i]["id"] . '\';';
}

mysql_query( $updated_sql );

?>

직렬화된 데이터의 예:

a:6:{s:5:"width";s:3:"400";s:6:"height";s:3:"530";s:14:"hwstring_small";s:22:"height='96' width='72'";s:4:"file";s:30:"2011/12/Amazonas-English-1.jpg";s:5:"sizes";a:13:{s:9:"thumbnail";a:3:{s:4:"file";s:30:"Amazonas-English-1-125x165.jpg";s:5:"width";s:3:"125";s:6:"height";s:3:"165";}s:6:"medium";a:3:{s:4:"file";s:30:"Amazonas-English-1-339x450.jpg";s:5:"width";s:3:"339";s:6:"height";s:3:"450";}s:5:"large";s:0:"";s:14:"post-thumbnail";a:3:{s:4:"file";s:30:"Amazonas-English-1-125x165.jpg";s:5:"width";s:3:"125";s:6:"height";s:3:"165";}s:23:"indexleft-species-thumb";a:3:{s:4:"file";s:30:"Amazonas-English-1-200x265.jpg";s:5:"width";s:3:"200";s:6:"height";s:3:"265";}s:13:"species-thumb";a:3:{s:4:"file";s:30:"Amazonas-English-1-288x381.jpg";s:5:"width";s:3:"288";s:6:"height";s:3:"381";}s:17:"indexheader-thumb";a:5:{s:4:"file";s:30:"Amazonas-English-1-400x300.jpg";s:5:"width";s:3:"400";s:6:"height";s:3:"300";s:4:"path";s:38:"2011/12/Amazonas-English-1-400x300.jpg";s:3:"url";s:88:"http://www.xxxxxxxxxxx.com/dev/wp-content/uploads/2011/12/Amazonas-English-1-400x300.jpg";}s:14:"random-thumb-1";a:3:{s:4:"file";s:28:"Amazonas-English-1-56x75.jpg";s:5:"width";s:2:"56";s:6:"height";s:2:"75";}s:14:"random-thumb-2";a:3:{s:4:"file";s:29:"Amazonas-English-1-75x100.jpg";s:5:"width";s:2:"75";s:6:"height";s:3:"100";}s:14:"random-thumb-3";a:3:{s:4:"file";s:29:"Amazonas-English-1-94x125.jpg";s:5:"width";s:2:"94";s:6:"height";s:3:"125";}s:14:"random-thumb-4";a:3:{s:4:"file";s:30:"Amazonas-English-1-113x150.jpg";s:5:"width";s:3:"113";s:6:"height";s:3:"150";}s:14:"random-thumb-5";a:3:{s:4:"file";s:30:"Amazonas-English-1-132x175.jpg";s:5:"width";s:3:"132";s:6:"height";s:3:"175";}s:13:"d4p-bbp-thumb";s:0:"";}s:10:"image_meta";a:10:{s:8:"aperture";s:1:"0";s:6:"credit";s:0:"";s:6:"camera";s:0:"";s:7:"caption";s:0:"";s:17:"created_timestamp";s:1:"0";s:9:"copyright";s:0:"";s:12:"focal_length";s:1:"0";s:3:"iso";s:1:"0";s:13:"shutter_speed";s:1:"0";s:5:"title";s:0:"";}}

추가 편집

불행하게도, 다른 사례들이 있습니다./dev/다음과 같은 다른 직렬화된 어레이의 경우:

'a:1:{i:0;a:5:{s:4:"type";s:5:"image";s:3:"loc";s:107:"/home/xxxxx/domains/xxxxxxxxx.com/public_html/dev/wp-content/sp-resources/forum-image-uploads/matt/2012/01/";...

아니면.

a:1:{i:0;a:5:{s:4:"data";s:88:"Your search - <b>link:http://www.xxxxxxxxx.com/dev/</b> - did not match any documents. ";...

이와 같이, 저는 단순하지 않다고 생각합니다.preg_replace(또는 콜백)이 그 묘기를 부리겠지만, 제 생각에는 고급이 할 수 있을 것 같습니다.


제 질문은 다음과 같습니다.

  1. 더 간단한 방법이 있을까요?!
  2. 위의 코드에 문제가 발생합니까?

저는 제 코드에 문제가 있는 것을 보는 것이 끔찍합니다(잘못된 프로그래머, 죄송합니다). 그리고 이 코드로 테스트를 실행하는 것에 대해 약간 걱정합니다.


최종 편집: 작업 코드

내 SQL 덤프가 거의100mb메모리가 무제한인 WAMP를 사용해야 했습니다.

<?php
    error_reporting(E_ALL);
    ini_set('display_errors', 'On');
    ini_set('memory_limit', '-1');

    $handle = @fopen("amend-this.sql", "r");
    if ($handle) {
        while (($buffer = fgets($handle, 4096)) !== false) {
          $newLine = preg_replace_callback('@s:(\d+)(:\\\"[^"]*www.seriouslyfish\.com)/dev@', create_function('$matches', 'return \'s:\'.($matches[1] - 4).$matches[2];'), $buffer);
          $newLine = preg_replace_callback('@s:(\d+)(:\\\"[^\\\"]*/home/sfish/domains/seriouslyfish\.com/public_html)/dev@', create_function('$matches', 'return \'s:\'.($matches[1] - 4).$matches[2];'), $newLine);
          $newLine = str_replace('http://dunc.seriouslyfish.com/dev/', 'http://www.seriouslyfish.com/', $newLine);
          $newLine = str_replace('http://www.seriouslyfish.com/dev/', 'http://www.seriouslyfish.com/', $newLine);
          $newLine = str_replace('/dev', '', $newLine);
          file_put_contents( "amended.sql", $newLine, FILE_APPEND );
        }
        fclose($handle);
    }
?>

이 코드는 나의 새로운 SQL 파일을 같은 디렉토리에 넣었습니다.X:\wamp\www)을 추가로 조작할 수 있습니다.

데이터 반복과 관련하여 몇 가지 문제가 있었는데, 67건의 사례가 있었습니다./dev어떤 이유에서인지 아직 파일에 남아 있지만, 저는 이 모든 것을 정리하기 위해 메모장++과 WinMerge를 사용했고, 결국 9천만자가 넘는 데이터베이스를 검색/교체하는 데 약 45분이 걸렸습니다.

동일한 문제가 발생했을 때 데이터베이스의 mysqdump를 실행한 다음 텍스트 편집기를 열고 값을 검색/교체한 후 SQL을 사용하여 새 데이터베이스를 만들었습니다.아주 간단하고, 놀라울 정도로 빠릅니다. 특히 일회성 작업에 적합합니다.

지적했듯이 직렬화된 데이터에 문제가 있으므로 간단한 PHP 파일로도 유사한 작업을 수행할 수 있습니다.

<?php
$handle = @fopen("/tmp/dump.sql", "r");
if ($handle) {
    while (($buffer = fgets($handle, 4096)) !== false) {
      $newLine = preg_replace_callback('@s:(\d+)(:\\\"[^"]*xxxxxxxxxxx\.com)/dev@', create_function('$matches', 'return \'s:\'.($matches[1] - 4).$matches[2];'), $buffer);
      $newLine = preg_replace_callback('@s:(\d+)(:\\\"[^\\\"]*xxxxxxxxxxx\.com/public_html)/dev@', create_function('$matches', 'return \'s:\'.($matches[1] - 4).$matches[2];'), $newLine);
      $newLine = str_replace('http://www.xxxxxxxxxxx.com/dev/', 'http://www.xxxxxxxxxxx.com/', $newLine);
      echo $newLine;
    }
    fclose($handle);
}
?>

참고: 이것은 mysqdump에서 작동합니다. 테스트 중인 경우, 다음을 제거해야 합니다.\\\ "의 spreg_replace_callbacks - 이것은 단지 내 sqdump 탈출 인용문입니다.

참고 사항:두 개의 사전 대체(일반 URL용 하나와 서버 경로용 하나)와 나머지 표준 URL용 하나가 있습니다.

프로그래머가 아닌 사람을 위한 직렬화 픽서 워드프레스 플러그인이 있습니다. http://davidcoveney.com/575/php-serialization-fix-for-wordpress-migrations/

PHP로도 할 수 있습니다.

또한, 여기 샘플 MySQL 코드가 있습니다. https://data.stackexchange.com/drupal%20answersmeta/query/80128/sql-search-and-replace

이것은 매우 위험한 도구이니 조심하세요.

WP CLI를 사용하면 안 될까요?

wp search-replace https://example.dev https://example.com

언급URL : https://stackoverflow.com/questions/10331843/writing-a-mysql-database-find-replace-script-in-php

반응형