¿Cómo implementar la actualización del complemento de WordPress que modifica la base de datos?

10

Desarrollo un complemento de WordPress, que tiene varias tablas de bases de datos propias. El complemento crea estas tablas cuando se activa y las elimina cuando se eliminan / desinstalan.

Tengo que implementar un proceso de actualización del complemento que actualiza el código del complemento y la estructura de las tablas. El caso más simple sería agregar una nueva columna a una de las tablas. El 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? ¿Hay alguna función incorporada de WordPress que pueda ayudar?

Misha Moroshko
fuente

Respuestas:

4

La forma correcta de hacer esto en estos días es incluir su esquema como un archivo en la fuente del complemento 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 real requerido es muy simple:

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

Esto creará y actualizará la base de datos para usted según sea necesario. Cuando lo verifiqué por última vez, no eliminó las columnas antiguas no utilizadas, por lo que deberá codificarlo mediante una verificación de versión. Esta es una característica hermosa de WordPress y un gran ahorro de tiempo. Tenga cuidado al crear el archivo schema.sql que copia el espaciado en una exportación de esquema mysql exactamente como el código dbDelta () tiene fama de ser muy exigente con el espaciado. También debe probar la versión de la base de datos y, si no es la última, llame a lo anterior para actualizar la base de datos. Es posible que también deba realizar actualizaciones específicas para cubrir los cambios que dbDelta () no realiza correctamente (por ejemplo, eliminar una columna). Es fácil escribir una prueba simple de lógica para ver si la versión se ha actualizado y hacer estas actualizaciones manuales a través de $ wpdb. Por ejemplo, puede colocar una columna que ahora no se utiliza.

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

Esto se simplifica al ejecutar código, disculpas si lo he roto en el proceso de simplificarlo para su publicación.

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

Brian C
fuente
En estos días he comenzado a tomar la versión de la base de datos desde el tiempo de modificación del archivo schema.sql. Esto significa que solo actualizar el archivo scheme.sql es suficiente para provocar una actualización de la base de datos; no es necesario recordar editar la versión de la base de datos. Algo así como: $ db_version = filemtime ("schema.sql");
Brian C
1
Entonces, si el tiempo de archivo cambia de algo externo como mover servidores, ¿la versión de mtime y db cambia?
Walf
El tiempo de archivo siempre está en GMT, y los servidores rara vez difieren en unos pocos segundos, por lo que es casi imposible que se active dos veces por eso. Sin embargo, incluso si se dispara nuevamente, no se hace daño ya que se ejecuta una vez y hace una comparación con el DB en vivo, obviamente sin cambiar nada. Esto es lo hermoso de dbDelta (): puede ejecutarse varias veces sin problemas. Buena pregunta, gracias.
Brian C
3

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

Cada vez que interactúa con una tabla personalizada (o cualquier tabla, en realidad) que debe pasar por $wpdb- en particular asegurarse de que está familiarizado con el preparemétodo que ayuda lata escapa consultas y evitar las inyecciones.

Ya debería estar familiarizado, ya que debería estar usándolo para crear la tabla. En su gancho de instalación, debería 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";

//Create custom table
$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 se activa el complemento (es decir, no solo se instala). Por lo tanto, se ejecutará cuando alguien actualice el complemento automáticamente . Nota: Si se actualizan reemplazando el complemento manualmente, entonces no lo hará, por lo que deberá activar el código anterior admin_initcuando se actualice su complemento (almacene el número de versión en la tabla de opciones, verifique con la versión actual) .

Ahora, normalmente no desea que el CREATE TABLEcomando SQL se ejecute cada vez que actualice el complemento, aquí es donde dBDelta()entra.

Antes de ejecutar el comando anterior, comprueba si la tabla existe. Además, verifica los tipos de columna. Entonces, si la tabla no existe, la crea, si es así, pero algunos tipos de columnas han cambiado, las actualiza y, si no existe una columna, la agrega.

Desafortunadamente, si elimina una columna de lo anterior, no elimina automáticamente la columna. Para eliminar columnas / tablas, debe especificarlas específicamente DROP(verificando que existan antes que usted).

Stephen Harris
fuente