Pulsa ESC para cerrar

Curso WordpressCurso Wordpress

Un mu-plugin con varios archivos y carpetas: cómo organizarlo para que WordPress lo cargue

Los mu-plugins (plugins de uso obligatorio) son perfectos para el código propio de un sitio: se cargan siempre, antes que los plugins normales, y nadie los puede desactivar por error desde el escritorio. En esta serie de guías los usamos mucho.

Pero cuando juntas varios, aparece una pregunta: ¿puedo ordenarlos en carpetas?

La regla: solo la primera altura

WordPress carga únicamente los archivos .php que están directamente en wp-content/mu-plugins/. Si pones una carpeta adentro, ignora todo lo que contiene.

wp-content/mu-plugins/
├── cwp-seguridad.php        ← se carga
├── cwp-rendimiento.php      ← se carga
└── cwp-sitio/
    └── correos.php          ← NO se carga

Por eso, para un mu-plugin con varios archivos, se usa un archivo cargador.

El archivo cargador

La estructura:

wp-content/mu-plugins/
├── cwp-sitio.php            ← el cargador
└── cwp-sitio/
    ├── seguridad.php
    ├── rendimiento.php
    ├── correos.php
    └── assets/
        ├── admin.css
        └── editor.js

Y el cargador, cwp-sitio.php:

<?php
/**
 * Plugin Name: Funciones del sitio (Curso WordPress)
 * Description: Carga los módulos de la carpeta cwp-sitio.
 */

defined( 'ABSPATH' ) || exit;

define( 'CWP_SITIO_DIR', __DIR__ . '/cwp-sitio/' );
define( 'CWP_SITIO_URL', plugins_url( 'cwp-sitio/', __FILE__ ) );

foreach ( array( 'seguridad', 'rendimiento', 'correos' ) as $modulo ) {
	$archivo = CWP_SITIO_DIR . $modulo . '.php';
	if ( is_readable( $archivo ) ) {
		require_once $archivo;
	}
}

Ventajas de una lista explícita (en vez de cargar «todo lo que haya en la carpeta»):

  • Controlas el orden de carga.
  • Para desactivar un módulo, lo quitas de la lista.
  • Un archivo de prueba o una copia de respaldo que dejes en la carpeta no se ejecuta por accidente.

Si prefieres cargar todos los archivos de la carpeta, puedes usar glob( CWP_SITIO_DIR . '*.php' ), pero entonces cualquier archivo .php que alguien suba ahí se ejecutará en cada visita. La lista explícita es más segura.

Scripts y estilos

Para enlazar archivos de la carpeta assets, usa la constante de URL que definimos. plugins_url() detecta que el archivo está en mu-plugins y arma la dirección correcta:

<?php
// Dentro de cwp-sitio/rendimiento.php, por ejemplo.
add_action( 'admin_enqueue_scripts', function () {
	wp_enqueue_style(
		'cwp-sitio-admin',
		CWP_SITIO_URL . 'assets/admin.css',
		array(),
		filemtime( CWP_SITIO_DIR . 'assets/admin.css' )
	);
} );

Usar filemtime() como versión hace que el navegador descargue el archivo nuevo cada vez que lo modificas.

Lo que no funciona en un mu-plugin

  • Activación y desactivación: register_activation_hook() y register_deactivation_hook() no se ejecutan nunca, porque un mu-plugin no se «activa». Si necesitas crear una tabla o una opción la primera vez, compruébalo tú: si la opción no existe, créala.
  • Actualizaciones automáticas: WordPress no actualiza mu-plugins. Los actualizas tú.
  • Aparecer en la lista de plugins normal: aparecen en Plugins → Imprescindibles, y solo el archivo cargador.
  • Traducciones automáticas del directorio: si tu mu-plugin tiene textos traducibles, cárgalos tú con load_muplugin_textdomain().

¿Cuándo pasar a un plugin normal?

Si tu código crece mucho, necesita activación, una pantalla de ajustes con su propio menú, o lo vas a usar en varios sitios, conviértelo en un plugin normal. Un mu-plugin es ideal para código propio del sitio, pequeño y que siempre debe estar activo.

Como los mu-plugins no se pueden desactivar desde el escritorio, un error de PHP en uno de ellos deja el sitio caído hasta que lo corrijas por FTP o terminal. Prueba cada cambio en una copia del sitio antes.

¿Cuántos mu-plugins tiene tu sitio? Cuéntanos en el foro cómo los organizas.