2012-04-26 8 views
7

Actualmente estoy en el proceso de volver a desarrollar mi sitio web personalizado a un CMS dirigido por WordPress.Escribiendo un script de búsqueda/reemplazo de bases de datos MySQL en PHP

El sitio web en el que he estado trabajando es simplemente mi URL existente más /dev/, es decir, http://my.website.com/dev/.

Voy a mover este sitio web a http://my.website.com durante el fin de semana, y como tal, tendrá que eliminar todas las referencias a la URL /dev/.

Lo que me gustaría hacer es, básicamente, un "buscar y reemplazar" para /dev en mi base de datos. Puedo ver exactamente en qué tablas tiene este valor, pero naturalmente, como en una instalación de WordPress, muchos de estos campos son datos serializados, lo que simplifica dump>open with notepad++>find & replace.

El código que he desarrollado para este fin está aquí:

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

?> 

Un ejemplo de los datos serializados:

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

EDITAR ADICIONAL

Por desgracia, hay otras instancias de /dev/ en o Ther matrices serializados, como este ejemplo:

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

O

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

Como tal, no creo que un simple preg_replace (o de devolución de llamada) harán el truco, pero ¿Supongo que uno avanzado podría?


Mis preguntas son:

  1. ¿Hay una manera más sencilla de hacer esto ?!
  2. ¿Encontrará el código anterior algún problema?

Soy horrible al ver problemas con mi código (mal programador, me disculpo) y por lo tanto un poco aprensivo acerca de ejecutar pruebas con este código.


edición final: el código de trabajo

Debido a que mi volcado SQL era casi 100mb, tuve que usar WAMP con memoria ilimitada.

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

Este código poner mi nuevo archivo SQL en el mismo directorio (X:\wamp\www) para mí para manipular aún más.

tuve algunos problemas con los datos de repetición, y hubo 67 casos de /dev todavía en el archivo por alguna razón, pero he usado Notepad++ y WinMerge para ordenar todo esto a cabo y al final me tomó alrededor de 45 minutos buscar/reemplazar una base de datos de más de 90 millones de caracteres.

+0

¿Qué intenta hacer al declarar $ look_at []? –

+0

Especifique las tablas/campos a los que se debe prestar atención al hacer la búsqueda/reemplazo. Hay una serie de campos en varias tablas que nunca contendrán ninguna referencia a '/ dev'. – dunc

Respuesta

6

Cuando tuve el mismo problema ejecuté un mysqldump de la base de datos, luego abrí en un editor de texto y simplemente busqué/reemplacé los valores, antes de usar el SQL para crear la nueva base de datos. Muy simple, sorprendentemente rápido, especialmente para uno.

Como se ha señalado, tiene el problema con datos serializados, por lo que podría hacer algo similar con un simple archivo 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); 
} 
?> 

Nota: esto funciona en un mysqldump, si estás probando, necesitarás eliminar el \\\ antes de " s en el preg_replace_callback s - esto es solo mysqldump escaping quotes.

También Nota: Hay dos sustituciones preg (una para las URL normales y una para las rutas del servidor), y una sustitución str para las URL estándar sobrantes.

+0

Hola Leonard. Lamentablemente, si hago esto, romperá mis datos serializados. La función 'serialize' de PHP cuenta con la longitud de las cadenas que contiene su matriz, es decir,' .com/dev/'es de 9 caracteres,' .com' es solo 4. PHP no reconocerá los datos serializados como serializados si el formato/longitud no son correctos. – dunc

+0

Ahh - Si mal no recuerdo, utilicé dev.domain.tld y cambié a www.domain.tld - perdón por eso. Si soy sincero, mi próximo paso sería ver si puedo buscar a un nivel superior, cambiar los datos serializados para tener la longitud correcta. – LeonardChallis

+0

Sí, eso es lo que trato de hacer con el código PHP, ya que no conozco ningún editor de texto que pueda tratar con datos serializados. – dunc

0

¿No podría usar WP CLI para esto?

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