Cómo crear un plugin de WordPress paso a paso, parte 4

Nov 10, 2023 | Backend Frontend Template Pro, Plugin, WordPress

En esta entrada aprendemos a que el plugin cree tablas personalizadas cuando se instala, y además a que también las elimine cuando se desinstale, si queremos. Además crearemos el cuerpo de datos base para las próximas entradas del tutorial.

Las tablas pueden ser creadas tanto en la versión gratuita de la plantilla de plugins para WordPress: Backend Frontend Template, disponible desde este enlace o desde GitHub, como en la versión profesional para luego poder tratar con los datos de forma automatizada, disponible aquí.

Contenido de la guía:

Las tablas a instalar

Para los próximos ejemplos se crearán tres tablas:

  • Carreras disponibles
  • Internalización de las carreras disponibles, para mostrar diferentes textos e imágenes según el idioma del visitante
  • Corredores inscritos, siendo las claves primarias el número de dorsal y y la carrera
BBDD a instalar de forma automática por el plugin

MySQL/MariaDB:

CREATE TABLE `wp_bft_pro_races`  (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `status` enum('active','bin') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'active',
  `datetime_created` datetime NULL DEFAULT NULL,
  `datetime_modified` datetime NULL DEFAULT NULL,
  `datetime_removed` datetime NULL DEFAULT NULL,
  `price` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'Students' ROW_FORMAT = Dynamic;

CREATE TABLE `wp_bft_pro_races_i18n`  (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `race_id` int(11) NOT NULL COMMENT 'Foreign Key',
  `language` char(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `datetime_created` datetime NULL DEFAULT NULL,
  `datetime_modified` datetime NULL DEFAULT NULL,
  `title_i18n` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `subtitle_i18n` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `image_i18n` int(10) NOT NULL,
  PRIMARY KEY (`race_id`, `language`) USING BTREE,
  UNIQUE INDEX `uk_wp_bft_pro_races_i18n_id`(`id`) USING BTREE,
  CONSTRAINT `fk_wp_bft_pro_races_i18n_race_id` FOREIGN KEY (`race_id`) REFERENCES `wp_bft_pro_races` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'Internationalization of course names' ROW_FORMAT = Dynamic;

CREATE TABLE `wp_bft_pro_runners`  (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `race_id` int(10) NOT NULL COMMENT 'Foreign Key',
  `bib` int(10) NOT NULL,
  `status` enum('active','bin') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'active',
  `datetime_created` datetime NULL DEFAULT NULL,
  `datetime_modified` datetime NULL DEFAULT NULL,
  `datetime_removed` datetime NULL DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `surname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`race_id`, `bib`) USING BTREE,
  UNIQUE INDEX `uk_wp_cdv_festivals_runners_id`(`id`) USING BTREE,
  CONSTRAINT `fk_wp_bft_pro_runners_race_id` FOREIGN KEY (`race_id`) REFERENCES `wp_bft_pro_races` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 224989 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'Students' ROW_FORMAT = Dynamic;

El nombre de las tablas

En el código MariaDB se ha puesto el nombre entero, pero en el código PHP no se pondrá “wp_bft_pro_races”, el nombre de la tabla real es “races”, ya que el sufijo “wp” es decidido por la instalación de WordPress en $wpdb->prefix, y “bfft_pro” es el slug del plugin.

Ejemplo: “CREATE TABLE `”.$wpdb->prefix.$plugin_slug.”_”.”races`”.

Activator y deactivator

Cuando se activa o ejecuta el plugin se ejecuta el archivo include/class-your-plugin-activator.php

Por defecto activator ejecuta database_install_and_or_upgrade de include/class-your-plugin-install-upgrade-deinstall-database.php

	public static function activate() {
		error_log("Your Plugin plugin: activate");

		$database_de_install = new Your_Plugin_Install_Upgrade_Deinstall_Database();
		$database_de_install->database_install_and_or_upgrade($database_de_install);

		wp_schedule_event( time(), 'hourly', 'bl_your_plugin_cronjob' );
	}

Cuando se desactiva el plugin se ejecuta el archivo include/class-your-plugin-deactivator.php

Por defecto deactivator ejecuta dabatase_erase de include/class-your-plugin-install-upgrade-deinstall-database.php, comentar o eliminar la llamada a database_erase si no queremos que se eliminen los datos cuando se desactive el plugin

	public static function deactivate() {
		error_log("Your Plugin plugin: deactivate");

		$database_de_install = new Your_Plugin_Install_Upgrade_Deinstall_Database();
		$database_de_install->dabatase_erase();

		//dabatase_erase() already clean cronjobs
	}

Instalación y/o actualización de la base de datos del plugin

En includes/class-your-plugin-install-upgrade-deinstall-database.php está la función database_install_and_or_upgrade.

Esta función está preparada para que se vayan añadiendo las diferentes versiones de la base de datos, de esta forma cuando ha habido una actualización sólo se ejecutará lo necesario gracias a $database_version_installed.

Y las actualizaciones en la base de datos se ejecutarán con $wpdb->query();, ejecutando siempre antes SET FOREIGN_KEY_CHECKS 0 y 1 para evitar problemas con las claves foráneas.

Mientras que explicarlo es difícil, viendo el código en seguida se entiende cómo funciona, recomiendo que analices primero este código esqueleto.

Esqueleto de la versión 1.0.0

$database_version_upgrade = "1.0.0";
if ( version_compare( $database_version_installed, $database_version_upgrade) < 0 ) {

	//Cleanup database
	if ($instantiated_class === NULL) {
		$this->dabatase_erase();
	}
	else {
		$instantiated_class->dabatase_erase();
	}

	error_log($plugin_title." plugin: database update $database_version_upgrade");

	$wpdb->query("SET FOREIGN_KEY_CHECKS = 0");

	$wpdb->query("CREATE TABLE...");

	$wpdb->query( "SET FOREIGN_KEY_CHECKS = 1");

	$your_plugin_languages = ["en", "es"];
	update_option( $plugin_slug."_"."languages", $your_plugin_languages);
	update_option( $plugin_slug."_"."language_admin", "en");

	
	$database_version_installed = $database_version_upgrade;
	update_option( $plugin_slug.'_database_version_installed', $database_version_installed);
}

Esqueleto de la actualización 1.0.1

$database_version_upgrade = "1.0.1";
if ( version_compare( $database_version_installed, $database_version_upgrade) < 0 ) {
	error_log($plugin_title." plugin: database update $database_version_upgrade");


	$wpdb->query("SET FOREIGN_KEY_CHECKS = 0");
	$wpdb->query("CREATE TABLE...");
	$wpdb->query( "SET FOREIGN_KEY_CHECKS = 1");

	$database_version_installed = $database_version_upgrade;
	update_option( $plugin_slug.'_database_version_installed', $database_version_installed);
}

Y en cualquier añadido psoterior sólo será necesario aumentar la cantidad de $database_version_upgrade en el siguiente trozo clonado.

Ejemplo real: para el ejemplo se considerará que wp_bft_pro_races y wp_bft_pro_races_i18n son de la versión 1.0.0 y que wp_bft_pro_runners se añadió en la versión 1.0.1. El código es de toda la función database_install_and_or_upgrade.

/**
 * Install the database
 *
 * Install the original database and upgrades if needed
 * 
 * This function is executed every time the plugin is called
 *
 * @since		1.0.0
 * @version		1.0.1
 */
public function database_install_and_or_upgrade($instantiated_class = NULL) {
	global $wpdb;

	/**
	 * Prefix of the settings and sub prefix of the plugin managed by WordPress
	 * 
	 * If changed '$plugin_slug = "your_plugin";', updated all the concurrences of the plugin
	 */
	$plugin_slug = "bft_pro";
	$plugin_title = "Your Plugin";

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

	$database_version_installed = get_option( $plugin_slug.'_database_version_installed', '0.0.0' );

	$charset_collate = $wpdb->get_charset_collate();

	/**
	 * Initial database
	 * 
	 * @since    1.0.0
	 */
	$database_version_upgrade = "1.0.0";
	if ( version_compare( $database_version_installed, $database_version_upgrade) < 0 ) {

		//Cleanup database
		if ($instantiated_class === NULL)
		{
			$this->dabatase_erase();
		}
		else
		{
			$instantiated_class->dabatase_erase();
		}

		error_log($plugin_title." plugin: database update $database_version_upgrade");

		//Install initial database
		$wpdb->query("SET FOREIGN_KEY_CHECKS = 0");

		/**
		 * Don't use "wp_your_plugin_some_table", use instead: ".$wpdb->prefix."your_plugin_some_table
		 * 
		 * The WordPress Instalation define the prefix, use '".$wpdb->prefix."your_plugin_some_table' isntead of 'wp_your_plugin_some_table'
		 */
		$wpdb->query("
			CREATE TABLE `".$wpdb->prefix.$plugin_slug."_"."races`  (
				`id` int(10) NOT NULL AUTO_INCREMENT,
				`status` enum('active','bin') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'active',
				`datetime_created` datetime NULL DEFAULT NULL,
				`datetime_modified` datetime NULL DEFAULT NULL,
				`datetime_removed` datetime NULL DEFAULT NULL,
				`price` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
				PRIMARY KEY (`id`) USING BTREE
			) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'Students' ROW_FORMAT = Dynamic;");

		$wpdb->query("
			CREATE TABLE `".$wpdb->prefix.$plugin_slug."_"."races_i18n`  (
				`id` int(10) NOT NULL AUTO_INCREMENT,
				`race_id` int(11) NOT NULL COMMENT 'Foreign Key',
				`language` char(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
				`datetime_created` datetime NULL DEFAULT NULL,
				`datetime_modified` datetime NULL DEFAULT NULL,
				`title_i18n` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
				`subtitle_i18n` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
				`image_i18n` int(10) NOT NULL,
				PRIMARY KEY (`race_id`, `language`) USING BTREE,
				UNIQUE INDEX `uk_".$wpdb->prefix.$plugin_slug."_"."races_i18n_id`(`id`) USING BTREE,
				CONSTRAINT `fk_".$wpdb->prefix.$plugin_slug."_"."races_i18n_race_id` FOREIGN KEY (`race_id`) REFERENCES `".$wpdb->prefix.$plugin_slug."_"."races` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
			) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'Internationalization of course names' ROW_FORMAT = Dynamic;");	

		$wpdb->query( "SET FOREIGN_KEY_CHECKS = 1");

		//Install initial Settings
		$your_plugin_languages = ["en", "es"];
		update_option( $plugin_slug."_"."languages", $your_plugin_languages);
		update_option( $plugin_slug."_"."language_admin", "en");
		update_option( $plugin_slug."_"."currency_id", "USD");
		
		$database_version_installed = $database_version_upgrade;
		update_option( $plugin_slug.'_database_version_installed', $database_version_installed);

		//Running the cronjobs
		wp_schedule_event( time(), 'hourly', 'bl_your_plugin_cronjob' );

	}
	/**
	 * Initial database
	 * 
	 * @since    1.0.1
	 */
	$database_version_upgrade = "1.0.1";
	if ( version_compare( $database_version_installed, $database_version_upgrade) < 0 ) {
		error_log($plugin_title." plugin: database update $database_version_upgrade");

		//Install initial database
		$wpdb->query("SET FOREIGN_KEY_CHECKS = 0");

		/**
		 * Don't use "wp_your_plugin_some_table", use instead: ".$wpdb->prefix."your_plugin_some_table
		 * 
		 * The WordPress Instalation define the prefix, use '".$wpdb->prefix."your_plugin_some_table' isntead of 'wp_your_plugin_some_table'
		 */
		$wpdb->query("
			CREATE TABLE `".$wpdb->prefix.$plugin_slug."_"."runners`  (
				`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
				`race_id` int(10) NOT NULL COMMENT 'Foreign Key',
				`bib` int(10) NOT NULL,
				`status` enum('active','bin') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'active',
				`datetime_created` datetime NULL DEFAULT NULL,
				`datetime_modified` datetime NULL DEFAULT NULL,
				`datetime_removed` datetime NULL DEFAULT NULL,
				`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
				`surname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
				PRIMARY KEY (`race_id`, `bib`) USING BTREE,
				UNIQUE INDEX `uk_wp_cdv_festivals_runners_id`(`id`) USING BTREE,
				CONSTRAINT `fk_".$wpdb->prefix.$plugin_slug."_"."runners_race_id` FOREIGN KEY (`race_id`) REFERENCES `".$wpdb->prefix.$plugin_slug."_"."races` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
			) ENGINE = InnoDB AUTO_INCREMENT = 224989 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'Students' ROW_FORMAT = Dynamic;");
		
		$database_version_installed = $database_version_upgrade;
		update_option( $plugin_slug.'_database_version_installed', $database_version_installed);

		//Running the cronjobs
		wp_schedule_event( time(), 'hourly', 'bl_your_plugin_cronjob' );

	}

	return ($database_version_installed);
}

Desinstalación del plugin

Para la desinstalación del plugin sólo será necesario añadir los DROP TABLE en dabatase_erase.

/**
 * Delete the database
 *
 * @since		1.0.0
 * @version		1.0.1
 */
public function dabatase_erase() {
	global $wpdb;

	/**
	 * Prefix of the settings and sub prefix of the plugin managed by WordPress
	 * 
	 * If changed '$plugin_slug = "your_plugin";', updated all the concurrences of the plugin
	 */
	$plugin_slug = "bft_pro";
	$plugin_title = "Your Plugin";

	error_log($plugin_title." plugin: deleting tables");

	$wpdb->query( "SET FOREIGN_KEY_CHECKS = 0");

	//Delete tables
	$wpdb->query( "DROP TABLE IF EXISTS `".$wpdb->prefix.$plugin_slug."_"."races`;");
	$wpdb->query( "DROP TABLE IF EXISTS `".$wpdb->prefix.$plugin_slug."_"."races_i18n`;");
	$wpdb->query( "DROP TABLE IF EXISTS `".$wpdb->prefix.$plugin_slug."_"."runners`;");

	$wpdb->query( "SET FOREIGN_KEY_CHECKS = 1");


	//Delete settings data
	delete_option($plugin_slug."_"."database_version_installed");
	delete_option($plugin_slug."_"."languages");
	delete_option($plugin_slug."_"."language_admin");
	delete_option($plugin_slug."_"."currency_id");

	//Stop the cronjobs
	wp_clear_scheduled_hook('bl_your_plugin_cronjob');
}

¿Necesitas más?

¡Próximamente más entradas de la guía!, aunque en Backend Frontend Template Pro: the WordPress Plugin Template tienes ya disponibles muchas páginas de ejemplo y textos explicativos, ¡no esperes y empieza ya a crear tu plugin!

0 comentarios

Enviar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Utilizamos Cookies propias y de terceros para mejorar nuestros servicios y para ofrecerte una mejor experiencia (por ejemplo, mostrando publicidad personalizada) mediante el análisis de tus hábitos de navegación (por ejemplo, páginas visitadas). Puedes aceptar todas las cookies pulsando el botón “Aceptar”. Para configurarlas, obtener más información o rechazar su uso, haz click AQUÍ

Los ajustes de cookies en esta web están configurados para «permitir las cookies» y ofrecerte la mejor experiencia de navegación posible. Si sigues usando esta web sin cambiar tus ajustes de cookies o haces clic en «Aceptar», estarás dando tu consentimiento a esto.

Cerrar