Cómo implementar actualización de plugin de WordPress que modifica la base de datos

6 oct 2012, 16:08:46
Vistas: 15.5K
Votos: 15

Desarrollo un plugin de WordPress, que tiene varias tablas de base de datos propias. El plugin crea estas tablas cuando se activa, y las elimina cuando se desinstala.

Necesito implementar un proceso de actualización del plugin que actualice tanto el código como la estructura de las tablas. El caso más simple sería añadir una nueva columna a una de las tablas. Un caso más complejo sería crear una nueva estructura de tablas y actualizar el contenido en consecuencia.

¿Cómo recomendarías resolver este problema? ¿Existe alguna función incorporada de WordPress que pueda ayudar?

0
Todas las respuestas a la pregunta 2
0

En resumen, sí, la clase $wpdb. Ver Codex para más información.

Cada vez que interactúes con una tabla personalizada (o cualquier tabla, realmente) deberías hacerlo a través de $wpdb - en particular, asegúrate de estar familiarizado con el método prepare que puede ayudar a escapar consultas y prevenir inyecciones.

Deberías estar familiarizado con esto, ya que deberías usarlo para crear la tabla. En tu hook de instalación deberías tener algo como:

$charset_collate = '';
if ( ! empty($wpdb->charset) )
    $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
if ( ! empty($wpdb->collate) )
    $charset_collate .= " COLLATE $wpdb->collate";

//Crear tabla personalizada
$sql_custom_table ="CREATE TABLE {$wpdb->prefix}my_table (
    id bigint(20) unsigned NOT NULL auto_increment,
    column_a varchar(255) default NULL,
    column_b varchar(255) default NULL,
    PRIMARY KEY  (id)
    ) $charset_collate; ";

require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql_custom_table);

Este código se ejecuta cada vez que el plugin se activa (es decir, no solo durante la instalación). Por lo tanto, se ejecutará cuando alguien actualice el plugin automáticamente. Nota: Si actualizan reemplazando el plugin manualmente, entonces no se ejecutará, por lo que necesitarás activar el código anterior en admin_init cuando tu plugin se actualice (almacena el número de versión en la tabla de opciones, compáralo con la versión actual).

Normalmente no querrías que el comando SQL CREATE TABLE se ejecutara cada vez que actualizas el plugin - aquí es donde entra dBDelta().

Antes de ejecutar el comando anterior, verifica si la tabla existe. Además, verifica los tipos de columna. Entonces, si la tabla no existe, la crea; si existe pero algunos tipos de columna han cambiado, los actualiza; y si una columna no existe, la añade.

Desafortunadamente, si eliminas una columna del código anterior, no la elimina automáticamente. Para eliminar columnas o tablas, necesitas específicamente usar DROP (verificando que existan antes de hacerlo).

6 oct 2012 17:22:21
3

La forma correcta de hacer esto actualmente es incluir tu esquema como un archivo en el código fuente del plugin y usar la función incorporada de WordPress dbDelta() para actualizar la base de datos según sea necesario usando ese esquema. El código requerido es muy simple:

$sql = file_get_contents( plugin_dir_path(__FILE__) . "/schema.sql" );
dbDelta( $sql );

Esto creará y actualizará la base de datos según sea necesario. Cuando lo verifiqué por última vez, no eliminaba las columnas antiguas no utilizadas, por lo que necesitarías codificar eso mediante una verificación de versión. Esta es una característica hermosa de WordPress y un gran ahorro de tiempo. Ten cuidado al crear el archivo schema.sql y copia el espaciado exactamente como en una exportación de esquema de mysql, ya que se dice que el código dbDelta() es muy exigente con los espacios. También deberías probar la versión de la base de datos y, si no es la más reciente, llamar al código anterior para actualizarla. También podrías necesitar hacer actualizaciones específicas para cubrir cambios que dbDelta() no maneja correctamente (por ejemplo, eliminar una columna). Es fácil escribir una simple prueba lógica if para ver si la versión ha sido actualizada y hacer estas actualizaciones manuales mediante $wpdb. Por ejemplo, podrías eliminar una columna que ya no se usa.

$installed_ver = get_option(MY_DB_VERSION);
$wpp = $wpdb->prefix . "mypluginname";
if ($installed_ver < 102)
        $wpdb->query("ALTER TABLE ${wpp}_movies DROP nft_date");
if ($installed_ver < 107)
        $wpdb->query("ALTER TABLE ${wpp}_movies CHANGE lastupdated "
        . "lastupdated TIMESTAMP on update CURRENT_TIMESTAMP "
        . "NOT NULL DEFAULT CURRENT_TIMESTAMP");

update_option(MY_DB_VERSION, $db_version);

Este código está simplificado de un código en funcionamiento, disculpas si lo he dañado en el proceso de simplificarlo para su publicación.

También ten en cuenta que a partir de WordPress 3.9.2, WordPress no siempre ejecuta el hook de activación al actualizar el plugin (específicamente, si se realiza una actualización masiva desde la página de Actualizaciones del Panel de Control).

21 sept 2014 03:44:06
Comentarios

Últimamente he empezado a tomar la versión de la base de datos a partir del tiempo de modificación del archivo schema.sql. Esto significa que con solo actualizar el archivo schema.sql es suficiente para provocar una actualización de la base de datos; no hay necesidad de recordar editar la versión de la base de datos. Algo como: $db_version = filemtime("schema.sql");

Brian C Brian C
19 sept 2019 12:40:00

Entonces, ¿si el tiempo del archivo cambia por algo externo como mover servidores, el mtime y la versión de la base de datos cambian?

Walf Walf
13 nov 2019 04:17:57

El tiempo del archivo siempre está en GMT, y los servidores rara vez difieren por unos segundos, así que es casi imposible que se dispare dos veces por eso. Sin embargo, incluso si se dispara nuevamente, no hay daño ya que se ejecuta una vez y hace una comparación contra la base de datos en vivo, obviamente sin cambiar nada. Esto es lo hermoso de dbDelta() - puede ejecutarse múltiples veces sin problema. Buena pregunta, gracias.

Brian C Brian C
13 nov 2019 08:39:19