Get a Free Consultation
Blog

Por qué la lógica de negocio debe vivir fuera del tema en la arquitectura de WordPress

WordPress carga el núcleo, luego los mu-plugins, los plugins y el tema al final. Colocar tipos de entrada y lógica de negocio en el tema hace que cada rediseño arriesgue romper tu aplicación.

Published on October 3, 2026 by Hector Felan Last updated on October 4, 2026 Reading Time: 14 minutes

Introducción

Muchos sitios de WordPress empiezan con buenas intenciones y terminan frágiles. Un equipo de desarrollo construye un tema personalizado, registra los tipos de entrada personalizados que el negocio necesita, agrega las taxonomías que organizan el contenido, conecta las relaciones entre los datos y coloca las reglas de negocio de apoyo directamente en los archivos del tema. Todo funciona. El sitio se lanza. Luego comienza un rediseño, se encarga un tema nuevo o llega una actualización importante del tema, y de pronto cada tipo de entrada personalizado, cada taxonomía y cada pieza de lógica que dependía de esos archivos tiene que reconstruirse o migrarse con cuidado. Los datos del negocio pueden seguir en la base de datos, pero el código que los define y protege desaparece.

Este patrón es común porque resulta conveniente durante la primera construcción. El tema es el lugar donde los desarrolladores ya trabajan. Es el lugar donde el cliente ve los cambios. Sin embargo, la conveniencia es temporal. Una vez que el tema se convierte en el contenedor de los modelos de datos y de las reglas de negocio, cada decisión futura sobre el tema arrastra el riesgo de romper la capa de aplicación. Ese riesgo aparece como lanzamientos retrasados, esfuerzo duplicado, pantallas de administración rotas, relaciones de contenido perdidas y problemas silenciosos de integridad de datos que solo salen a la luz después de que el nuevo tema está en producción.

El propio orden de carga de WordPress explica por qué ocurre esto y dónde debió vivir el código desde el principio.

Por qué el código personalizado atado al tema se vuelve costoso

Cuando los tipos de entrada personalizados, las taxonomías y la lógica de apoyo viven dentro de un tema, se tratan como código de presentación aunque no lo sean. La presentación puede cambiar. El modelo de datos subyacente normalmente no puede hacerlo sin un costo real. Una empresa que ha acumulado durante años entradas de un tipo personalizado, taxonomías relacionadas y campos personalizados ahora enfrenta la reconstrucción del código de registro, de las reglas de reescritura, del mapeo de capacidades y de cualquier gancho que dependiera de esas definiciones. En la práctica este trabajo rara vez es una copia limpia. Las convenciones de nombres se desvían, los argumentos cambian y aparecen efectos secundarios en otros plugins o plantillas que asumían que las definiciones antiguas siempre estarían presentes.

El costo no se limita a horas de desarrollo. Los equipos editoriales pierden interfaces familiares. Los procesos automatizados que dependían de tipos de entrada específicos dejan de funcionar. Las estructuras de SEO que dependían de reglas de reescritura particulares se desplazan. Las herramientas de reportes que consultaban ciertas claves de meta devuelven resultados incompletos. Todo esto ocurre porque nunca se trazó el límite arquitectónico entre la capa de aplicación y la capa de presentación.

La decisión que enfrenta todo proyecto de WordPress

Todo proyecto serio de WordPress termina enfrentando la misma elección. ¿Debe la funcionalidad personalizada vivir en el tema, en un plugin normal o en un plugin de uso obligatorio? La respuesta no es cuestión de preferencia ni de velocidad de entrega. Es cuestión de qué debe sobrevivir a un cambio de tema y qué puede cambiar con seguridad junto con el diseño visual.

Los temas existen para controlar la salida y la experiencia editorial de esa salida. Los plugins y los plugins de uso obligatorio existen para definir capacidades, estructuras de datos y comportamiento de negocio que deben permanecer estables a través de rediseños visuales. Tratar el tema como el hogar de los modelos de datos colapsa esa distinción y obliga a reescribir la capa de aplicación cada vez que se actualiza la capa de diseño.

Comprender el orden de carga de WordPress

WordPress no carga todo al mismo tiempo. Sigue una secuencia deliberada que determina qué código está disponible en cada etapa y qué código puede depender con seguridad del código anterior.

El núcleo

El núcleo de WordPress se carga primero. Esto incluye la conexión a la base de datos, la caché de objetos cuando está configurada, el manejo básico de la solicitud y las APIs fundamentales que usará todo lo demás. En esta etapa todavía no existen los tipos de entrada personalizados ni las taxonomías del proyecto. El núcleo se mantiene deliberadamente ligero para que el resto de la pila pueda extenderlo.

Plugins de uso obligatorio

Después vienen los plugins de uso obligatorio, a menudo abreviados como mu-plugins. Se cargan automáticamente desde el directorio de mu-plugins y no se pueden desactivar a través de la interfaz normal de administración. Como se cargan antes que los plugins regulares y antes del tema, son el lugar más temprano donde el código personalizado puede registrar tipos de entrada, taxonomías y lógica de negocio fundamental sin salir del núcleo. El código que vive aquí está disponible para todas las capas posteriores.

El directorio de plugins de uso obligatorio se encuentra dentro del directorio de contenido de WordPress. Su ubicación estándar es la siguiente ruta.

wp-content/mu-plugins/
├── application-core.php
└── app-core/
    ├── post-types.php
    ├── taxonomies.php
    ├── capabilities.php
    ├── relationships.php
    └── api/
        ├── api-endpoint.php
        └── newsletter.php

WordPress incluye automáticamente cada archivo PHP colocado directamente en esa carpeta. No carga de forma automática los archivos que se encuentran dentro de subdirectorios. Para cualquier cosa que vaya más allá de un solo archivo pequeño, el enfoque práctico consiste en colocar un archivo cargador en la raíz del directorio de mu-plugins y hacer que ese cargador incorpore los módulos separados desde un subdirectorio.

Un cargador típico se ve de la siguiente manera.

<?php
/**
 * Plugin Name: Project Application Layer
 * Description: Registra los modelos de datos principales
 *              y la lógica de negocio que debe sobrevivir
 *              a los cambios de tema.
 *              
 * Version:     1.0.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * Cambia este valor cuanto agregues o modifiques un CPT, taxonomía o un slug rewrite.
 */
define( 'BMC_REWRITE_VERSION', '1.0.0' );

require_once __DIR__ . '/app-core/post-types.php';
require_once __DIR__ . '/app-core/taxonomies.php';
require_once __DIR__ . '/app-core/capabilities.php';
require_once __DIR__ . '/app-core/relationships.php';
require_once __DIR__ . '/app-core/api/api-endpoint.php';

// ó

define( 'PATH', __DIR__ . '/app-core/' );

foreach ( array(
	'post-types.php',
	'taxonomies.php',
	'capabilities.php',
	'relationships.php',
	'api/api-endpoint.php',
) as $file ) {
	require_once PATH . $file;
}

// Agrega esta linea despues de cualquier registro
add_action( 'init', 'bmc_maybe_flush_rewrite_rules', 99 );

// Actualización única de las reglas de reescritura (sustituye al *hook* de activación del que carecen los *mu-plugins*).
function bmc_maybe_flush_rewrite_rules() {
	if ( get_option( 'bmc_rewrite_version' ) !== BMC_REWRITE_VERSION ) {
		flush_rewrite_rules( false ); // soft flush: skips rewriting .htaccess.
		update_option( 'bmc_rewrite_version', BMC_REWRITE_VERSION, false );
	}
}

// Los prefijos BMC_ and bmc_ significan "BoostMonitor Core", los puedes cambiar a tu preferencia.

Cada archivo requerido contiene únicamente el registro o la lógica enfocada de la que es responsable. El cargador mismo se mantiene mínimo y permanece como el único punto de entrada que WordPress descubre de forma automática.

Plugins activos

Después de los plugins de uso obligatorio, WordPress carga los plugins activos en el orden determinado por sus nombres de archivo y por las reglas de activación de red. Esta es la capa donde pertenece la mayor parte de la funcionalidad reutilizable. Un plugin personalizado bien estructurado puede registrar el modelo de datos completo del sitio, exponer endpoints REST, aplicar capacidades y proporcionar los servicios que tanto el tema como otros plugins consumirán. Como los plugins sobreviven a los cambios de tema, el modelo de datos permanece intacto cuando cambia el diseño visual.

El tema

El tema activo se carga al final. Para cuando se ejecutan el archivo de funciones y las plantillas del tema, el núcleo, los plugins de uso obligatorio y los plugins activos ya han definido los tipos de entrada disponibles, las taxonomías y los ganchos. El trabajo del tema es decidir cómo se muestra esa data ya registrada y cómo se siente la interfaz editorial. Cuando un tema también intenta registrar el modelo de datos, está registrando algo que desaparecerá en el momento en que se active un tema diferente.

Qué ocurre cuando la lógica de negocio vive en el tema

Colocar tipos de entrada personalizados y taxonomías dentro del tema crea una dependencia oculta. La base de datos sigue conteniendo las entradas, pero WordPress ya no sabe cómo interpretarlas una vez que el tema que registró los tipos se desactiva. Los menús de administración desaparecen. El tipo de entrada deja de aparecer en las consultas que dependen del nombre registrado. Las reglas de reescritura que dependían del registro se vacían o quedan en un estado inconsistente. Cualquier plantilla o plugin que asumía que el tipo de entrada siempre estaría presente comienza a fallar de maneras sutiles.

El mismo problema aparece con la lógica de apoyo. Las comprobaciones de capacidades, el registro de cajas meta, los ganchos de guardado de entradas y el código de gestión de relaciones que vivían en el tema dejan de ejecutarse. El resultado no siempre es una pantalla blanca dramática. Con más frecuencia es una erosión gradual de la funcionalidad que obliga a los desarrolladores a reconstruir las piezas faltantes bajo presión de tiempo mientras se termina el nuevo tema.

Bajo el capó del arranque de WordPress

Cuando llega una solicitud, WordPress comienza cargando la configuración y estableciendo la conexión a la base de datos. Luego incluye los plugins de uso obligatorio, seguidos de los plugins activos, y solo después carga el tema. Las funciones de registro de tipos de entrada y taxonomías suelen engancharse a la acción init. Como init se dispara después de que se han cargado los plugins, cualquier registro que ocurra dentro de un plugin está disponible para el tema. El registro que ocurre solo dentro del tema está disponible únicamente mientras ese tema permanezca activo.

Esta secuencia no es un accidente. Es el mecanismo que permite que la capa de aplicación sea estable mientras la capa de presentación permanece reemplazable. Cuando los equipos ignoran la secuencia y colocan el registro dentro del tema, convierten de hecho la capa de aplicación en algo temporal. Las decisiones arquitectónicas futuras quedan entonces limitadas por la necesidad de preservar o recrear ese código temporal.

Una consecuencia práctica aparece durante el desarrollo local y el entorno de pruebas. Cambiar de tema para probar un rediseño desactiva de inmediato el modelo de datos si este vivía en el tema anterior. Los desarrolladores deben mantener el tema antiguo activo en paralelo o extraer el código de registro antes de poder evaluar con seguridad el nuevo diseño. Ambos enfoques agregan fricción que nunca habría existido si el modelo de datos hubiera vivido en un plugin desde el principio.

Qué recomendamos

Para cualquier proyecto de WordPress que defina sus propios tipos de contenido, taxonomías o reglas de negocio no triviales, coloca ese código en un plugin personalizado o en un plugin de uso obligatorio en lugar del tema. El tema debe consumir los tipos registrados y proporcionar las plantillas y la experiencia editorial. No debe poseer la definición de los tipos mismos.

Usa un plugin de uso obligatorio cuando la funcionalidad es fundamental para todo el sitio y nunca debe desactivarse, ni siquiera por accidente. Usa un plugin personalizado normal cuando la funcionalidad sigue siendo específica del proyecto pero puede activarse o versionarse de forma legítima e independiente. Mantén el tema enfocado en la presentación, los patrones de bloques, la jerarquía de plantillas y la interfaz editorial controlada que se apoya sobre el modelo de datos ya registrado.

Hay excepciones limitadas. Los ayudantes puramente presentacionales que no tienen sentido fuera de un diseño visual particular pueden vivir en el tema. Todo lo que define lo que el sitio es, en lugar de cómo se ve una versión particular del sitio, pertenece fuera del tema.

Cómo abordamos la arquitectura en Boostmonitor

En Boostmonitor tratamos la separación entre la capa de aplicación y la capa de presentación como un punto de partida no negociable. Cuando comenzamos un proyecto identificamos los modelos de datos y las reglas de negocio que deben sobrevivir a cualquier rediseño futuro y los colocamos en plugins dedicados o en plugins de uso obligatorio antes de escribir la primera plantilla. Los tipos de entrada personalizados, las taxonomías, los mapas de capacidades y la lógica de negocio central se registran temprano y permanecen disponibles sin importar qué tema esté activo.

Este enfoque nos permite rediseñar, reconstruir o reemplazar un tema sin tocar la aplicación subyacente. También hace que el sitio sea más comprobable, porque el modelo de datos puede ejercitarse de forma independiente de cualquier conjunto particular de plantillas. Cuando un cliente necesita más adelante una nueva cara pública o una experiencia editorial diferente, el trabajo se mantiene enfocado en la capa de presentación en lugar de convertirse en una reconstrucción de años de lógica de negocio acumulada.

Aplicamos la misma disciplina a aplicaciones más grandes de WordPress, portales de clientes y configuraciones headless. El principio permanece constante. WordPress es capaz de impulsar sistemas de negocio duraderos. La limitación aparece solo cuando la arquitectura mezcla código de presentación temporal con código de aplicación permanente.

El orden de carga no es simplemente un detalle técnico. Es el mapa que muestra dónde debe vivir cada tipo de código si el sitio va a permanecer mantenible a medida que el negocio evoluciona.

Preguntas frecuentes

Puedo mover tipos de entrada personalizados existentes de un tema a un plugin sin perder datos

Sí. Las entradas mismas permanecen en la base de datos. Registras los mismos nombres de tipos de entrada y argumentos dentro de un plugin, desactivas el registro del tema y vacías las reglas de reescritura. El contenido existente vuelve a estar disponible bajo los tipos recién registrados. Se requiere cuidado con cualquier caja meta, gancho de guardado o comprobación de capacidades que también viviera en el tema, porque esos elementos también deben moverse.

Un plugin de uso obligatorio siempre es mejor que un plugin normal para los modelos de datos

No siempre. Los plugins de uso obligatorio no se pueden desactivar a través de la interfaz de administración, lo que los hace apropiados para código verdaderamente fundamental. Los plugins normales son preferibles cuando se desea control de versiones, un control de activación más claro o la posibilidad de desactivar la funcionalidad durante la depuración. Ambos mantienen el código fuera del tema.

Qué pasa con los temas de bloques y la edición completa del sitio

El mismo principio se aplica. Los temas de bloques todavía se cargan después de los plugins. Los tipos de entrada personalizados y las taxonomías deben seguir registrándose en un plugin para que el modelo de datos sobreviva a cualquier cambio futuro de tema o de conjunto de plantillas. La edición completa del sitio mejora la capa de presentación. No cambia la necesidad de mantener la capa de aplicación independiente.

Este enfoque ralentiza la construcción inicial

Agrega una pequeña cantidad de estructura al principio y elimina costos mucho mayores más adelante. Registrar tipos en un plugin requiere aproximadamente el mismo esfuerzo que registrarlos en un tema. La diferencia aparece cuando llega el primer rediseño y el modelo de datos no tiene que reconstruirse.