2012-04-26 40 views
7

Obecnie jestem w trakcie przebudowy mojej strony zindywidualizowanej na oparty na WordPressie CMS.Pisanie skryptu znajdowania/zamiany bazy danych MySQL w PHP

Strona, nad którą pracowałem, to po prostu mój istniejący adres URL plus /dev/, tj. http://my.website.com/dev/.

Będę przenosić tę stronę internetową pod numer http://my.website.com w ciągu weekendu i jako taka będzie musiała usunąć wszystkie odniesienia do adresu URL /dev/.

Co chcę zrobić, to "znajdowanie i zamiana" dla /dev w mojej bazie danych. Widzę dokładnie, które tabele mają tę wartość, ale naturalnie, jak na instalację WordPressa, sporo z tych pól jest serializowanych danych - co zepsuje prosty prosty kod: dump>>find & replace.

Kod mam opracowane do tego celu jest tutaj:

<?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); 

?> 

Przykładem danych odcinkach:

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:"";}} 

DODATKOWE EDIT

Niestety, istnieją inne instancje /dev/ w o Ther seryjne tablice, takie jak ten przykład:

'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/";...

Albo

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. ";...

Jako takie, nie sądzę prosty preg_replace (lub zwrotnego) rade, ale Sądzę, że może ktoś zaawansowany?


Moje pytania są następujące:

  1. Czy istnieje prostszy sposób to zrobić ?!
  2. Czy powyższy kod napotka jakieś problemy?

Jestem okropny z powodu problemów z moim kodem (zły programista, przepraszam) i jako taki mały lęk przed uruchomieniem testów z tym kodem.


FINAL EDIT: KODEKS PRACY

Ponieważ mój SQL zrzut był prawie 100mb, musiałem użyć WAMP z nieograniczoną pamięcią.

<?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)/[email protected]', create_function('$matches', 'return \'s:\'.($matches[1] - 4).$matches[2];'), $buffer); 
      $newLine = preg_replace_callback('@s:(\d+)(:\\\"[^\\\"]*/home/sfish/domains/seriouslyfish\.com/public_html)/[email protected]', 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); 
    } 
?> 

Ten kod umieścić mój nowy plik SQL do tego samego katalogu (X:\wamp\www) dla mnie, aby manipulować dalej.

miałem kilka problemów z danymi powtórzy, a tam były 67 przypadki /dev jeszcze w pliku z jakiegoś powodu, ale użyłem Notepad++ i WinMerge uporządkować to wszystko się w końcu zajęło mi około 45 minut wyszukać/zastąpić bazę danych zawierającą ponad 90 milionów znaków.

+0

Co próbujesz zrobić z deklaracją $ look_at []? –

+0

Należy określić tabele/pola, które należy wziąć pod uwagę podczas wyszukiwania/zastępowania. W wielu tabelach znajduje się wiele pól, które nigdy nie będą zawierały odniesienia do '/ dev'. – dunc

Odpowiedz

6

Kiedy miałem ten sam problem, uruchomiłem mysqldump bazy danych, następnie otworzyłem w edytorze tekstowym i po prostu przeszukano/zastąpiłem wartości, zanim użyłem SQL do stworzenia nowej bazy danych. Całkiem proste, zaskakująco szybkie, zwłaszcza jednorazowe.

Jak podkreślił, masz problem z danych odcinkach, więc można zrobić coś podobnego z prostym pliku PHP:

<?php 
$handle = @fopen("/tmp/dump.sql", "r"); 
if ($handle) { 
    while (($buffer = fgets($handle, 4096)) !== false) { 
     $newLine = preg_replace_callback('@s:(\d+)(:\\\"[^"]*xxxxxxxxxxx\.com)/[email protected]', create_function('$matches', 'return \'s:\'.($matches[1] - 4).$matches[2];'), $buffer); 
     $newLine = preg_replace_callback('@s:(\d+)(:\\\"[^\\\"]*xxxxxxxxxxx\.com/public_html)/[email protected]', 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); 
} 
?> 

Uwaga: to działa na mysqldump, jeśli jesteś testowanie, musisz usunąć \\\ przed " s w s - to tylko mysqldump uciekając cytaty.

Uwaga: Dostępne są dwa pre-zamienniki (jeden dla zwykłych adresów URL i jeden dla ścieżek serwera) i jeden str zastępuje standardowe pozostałe URL-e.

+0

Cześć Leonard. Niestety, jeśli to zrobię, złamie moje zserializowane dane. Funkcja PHP "serializacji" liczy się na długości łańcuchów zawartych w jej tablicy, np. '.com/dev /' ma 9 znaków, '.com' to tylko 4. PHP nie rozpozna danych zserializowanych jako serializowane, jeśli format/długości są nieprawidłowe. – dunc

+0

Ahh - Jeśli dobrze pamiętam, użyłem dev.domain.tld i zmieniono na www.domain.tld - przykro mi z tego powodu. Jeśli mam być szczery, moim następnym krokiem będzie sprawdzenie, czy mogę przeszukać wyższy poziom, zmienić zserializowane dane, by miały odpowiednią długość. – LeonardChallis

+0

Tak, właśnie to próbuję zrobić z kodem PHP, ponieważ nie znam żadnego edytora tekstu, który mógłby zajmować się serializowanymi danymi. – dunc

0

Nie możesz po prostu użyć WPI WPI do tego?

wp search-replace https://example.dev https://example.com 
Powiązane problemy