Open source · Ata
Lleva tu plugin de WordPress al siguiente nivel.
Con estructura MVC-S.
ATA ayuda a los desarrolladores de plugins de WordPress a mantener ordenado y mantenible un código que no para de crecer, gracias al patrón de diseño MVC.
Para desarrolladores de plugins de WordPress
Una carpeta para cada cosa.
ATA da a cada plugin la misma estructura predecible, para que el código siga ordenado y mantenible a medida que crece.
ATA Folder STRUCTURE
your-plugin-name/
├── app/
│ ├── apis/ # REST API endpoint classes
│ ├── controllers/ # Controller classes
│ ├── helpers/ # Global helper functions
│ ├── models/ # Data logic (database interaction)
│ │ └── structures/ # Optional: DTOs/data structure classes
│ ├── routes/ # API and custom URL definitions
│ ├── services/ # Business logic layer
│ └── views/ # View files (HTML/PHP templates)
│
├── base/ # Base classes your app classes extend
├── config/ # Plugin-wide configuration
├── constants/ # Custom constant definitions
├── inc/ # Bootstrapping and initialization files
├── vendor/ # Composer dependencies (includes the core ATA framework)
│
└── your-plugin-name.php # The main plugin entry file
Los principios básicos de Ata.
Estructurado de serie
ATA ofrece una estructura de directorios predefinida que separa de forma lógica las distintas partes de tu plugin.
Orientado a objetos ante todo
Fomenta escribir código en clases en lugar de funciones procedurales, lo que mejora la reutilización y la organización del código.
Separación clara de responsabilidades
Implementa una variante del patrón MVC para que la lógica, los datos y la presentación se mantengan en capas separadas.
Enrutamiento simplificado
ATA incluye un router integrado que hace que registrar endpoints personalizados de la REST API o URL personalizadas sea sencillo y declarativo.
Diferencias clave
¿Qué es MVC-S?
ATA promueve una variante del patrón Modelo-Vista-Controlador (MVC) a la que llamamos MVC-S (Model-View-Controller-Services).
Controlador (el motor central)
El Controlador es el núcleo del funcionamiento de tu plugin. Se encarga de gestionar las peticiones entrantes, registrar todos los hooks y filtros de WordPress y controlar el flujo de la aplicación. En plugins sencillos, el Controlador puede encargarse directamente de toda la lógica y del acceso a datos. En aplicaciones más complejas, su papel evoluciona hasta convertirse en un orquestador: llama a un Servicio para la lógica de negocio o a un Modelo para los datos, y después pasa los resultados a una Vista para renderizarlos.
Vista (la capa de presentación)
La Vista es una capa opcional para generar la salida HTML. Recibe datos del Controlador y los renderiza. Una Vista debe contener la mínima lógica PHP posible y centrarse solo en mostrar los datos que recibe.
Modelo (la capa de datos)
La única responsabilidad del Modelo es interactuar directamente con la base de datos. Dentro de una clase Modelo puedes acceder al objeto de base de datos de WordPress mediante $this->db (p. ej., $this->db->get_results(...)). Esta capa es opcional; si tu plugin no interactúa con la base de datos, no la necesitas.
Servicio (la capa de lógica)
La capa de Servicio es un lugar opcional pero recomendado para la lógica de negocio principal de tu plugin. Cuando la lógica se vuelve demasiado compleja para un Controlador, conviene extraerla a un Servicio. Así los Controladores se mantienen ligeros y centrados en gestionar peticiones.
Plugin de ejemplo
Polylang RestAPI Helper
El plugin polylang-restapi-helper es un ejemplo perfecto y concreto del framework ATA.
Cómo aplicar ATA MVC a tu plugin de WordPress
Documentación
Cómo empezar a usar ATA en tu plugin, de forma rápida y sencilla
El ciclo de vida del plugin & el controlador principal
Todo plugin ATA lo gestiona un Controlador raíz central. Este controlador principal es el punto de entrada de todas las funciones del plugin y se encarga de gestionar su ciclo de vida.
1. El archivo principal del plugin (your-plugin-name.php) Este archivo es mínimo. Su única función es definir las constantes esenciales, cargar el framework ATA e instanciar tu controlador principal.
// in your-plugin-name.php
namespace YourPluginNamespace;
// ... define constants ...
// Load the framework and all its dependencies
require_once PLUGIN_PATH . '/inc/main.php';
// Instantiate the one and only root controller
$my_plugin = new MainController();
// Hook into WordPress's activation/deactivation events
register_activation_hook(PLUGIN_FILE, [$my_plugin, 'activate']);
register_deactivation_hook(PLUGIN_FILE, [$my_plugin, 'deactivate']);
2. El controlador principal (app/controllers/main-controller.php) Este controlador contiene la lógica de activación/desactivación y, sobre todo, carga todos los demás controladores. Aquí puedes cargar funciones de forma condicional según si hay otros plugins activos, ahorrando memoria y evitando errores.
// in app/controllers/main-controller.php
namespace YourPluginNamespace;
class MainController extends Controller
{
public function __construct()
{
parent::__construct();
$this->load_features();
}
// Load other controllers for specific features
private function load_features()
{
// Always load the admin UI and asset controllers
(new AdminUiController())->main();
(new AssetsController())->main();
// **Conditionally load features**
// Only load the WooCommerce compatibility layer if WooCommerce is active
if (is_plugin_active('woocommerce/woocommerce.php')) {
(new WooCommerceController())->main();
}
}
// Logic for when the plugin is activated (e.g., create DB tables)
public function activate()
{
// ... your activation code ...
}
// Logic for when the plugin is deactivated (e.g., remove DB tables)
public function deactivate()
{
// ... your deactivation code ...
}
}
Añadir una página o pestaña al panel de administración de WordPress
ATA ofrece una interfaz fluida para crear fácilmente páginas de administración con varias pestañas. Todo se gestiona desde un controlador.
// in app/controllers/admin-ui-controller.php
namespace YourPluginNamespace;
class AdminUiController extends Controller
{
public function main()
{
$this->add_wp_admin_pages();
}
private function add_wp_admin_pages()
{
// Create a top-level page titled "My Plugin"
$this->admin_page('My Plugin')
// Only users who can 'manage_options' can see it
->permission('manage_options')
// Add a "Dashboard" tab (calls the 'dashboard_page' method)
->add_tab('Dashboard', 'dashboard_page')
// Add a "Settings" tab (calls the 'settings_page' method)
->add_tab('Settings', 'settings_page')
// Register the page and all its tabs
->register();
}
// This method is called when the 'Dashboard' tab is active
public function dashboard_page()
{
$this->view = 'dashboard'; // Renders views/dashboard-view.php
}
// This method is called when the 'Settings' tab is active
public function settings_page()
{
$this->view = 'settings'; // Renders views/settings-view.php
}
}
Engancharse a un hook de WordPress (Action)
ATA ofrece un práctico método auxiliar on() en su controlador base para registrar hooks de acción. El constructor o un método main() de tu controlador es el lugar ideal para registrar todos los hooks.
// in app/controllers/footer-message-controller.php
namespace YourPluginNamespace;
class FooterMessageController extends Controller
{
public function main()
{
// Hook into 'wp_footer' to call the 'add_message' method
$this->on('wp_footer', 'add_message');
}
public function add_message()
{
echo "";
}
}
Usar los filtros de WordPress
Igual que con las acciones, puedes usar el método auxiliar filter() para modificar datos.
// in app/controllers/content-controller.php
namespace YourPluginNamespace;
class ContentController extends Controller
{
public function main()
{
// Hook into 'the_content' to modify post content
$this->filter('the_content', 'add_author_bio');
}
public function add_author_bio($content)
{
if (is_single() && in_the_loop() && is_main_query()) {
$author_bio = '';
return $content . $author_bio;
}
return $content;
}
}
Añadir un endpoint a la REST API de WordPress
Paso 1: registra la ruta en app/routes/main-routes.php. Así WordPress sabe que tu URL existe y qué método debe gestionarla.
// in app/routes/main-routes.php
namespace YourPluginNamespace;
$ata_router->api_version('my-plugin/v1');
$ata_router->api_method('GET')->api('/products')->call('ProductsApi::get_all_products');
Paso 2: crea una clase API en app/apis/ que contenga la lógica del endpoint.
// in app/apis/products-api.php
namespace YourPluginNamespace;
class ProductsApi extends Api {
public function get_all_products() {
// ... logic to get products ...
return $this->send_success('Products retrieved.', ['products' => '...']);
}
}
¿Cómo funciona el enrutamiento?
El archivo de rutas (app/routes/main-routes.php) es una función potente pero opcional. Su único cometido es actuar como centralita, indicando a WordPress cómo gestionar determinadas URL personalizadas. Si tu plugin no necesita URL personalizadas ni una REST API, no tienes por qué usarlo.
- Para REST API: usa el método
api(). Registra un nuevo endpoint bajo/wp-json/.// Registers: example.com/wp-json/my-plugin/v1/orders $ata_router->api_version('my-plugin/v1'); $ata_router->api('/orders')->call('MyOrdersApi::get_orders'); - Para URL personalizadas en el frontend: usa el método
page(). Crea una página virtual sin necesidad de una entrada de tipo Página de WordPress.// Registers: example.com/my-custom-url/ $ata_router->page('/my-custom-url')->call('MyPageController::show_page');
¿Para qué sirven los directorios principales opcionales?
app/views
Este directorio contiene tus plantillas HTML. Solo es necesario si tu plugin genera una interfaz de usuario, como una página de ajustes en el panel o una página personalizada en el frontend. Los plugins que solo ofrecen funciones en segundo plano o una REST API probablemente no tendrán un directorio views.
models/structures (DTO)
Este directorio es para los Data Transfer Objects (DTO). Un DTO es una clase sencilla que define la forma de los datos que se pasan de un sitio a otro. Este directorio es opcional y puede que muchos plugins no lo necesiten. Resulta especialmente útil cuando necesitas imponer una estructura de datos estricta, sobre todo al comunicarte con una API externa.
Tu historia de éxito podría ser la próxima.
¿Tienes preguntas? Estamos aquí para ayudarte a dar el paso correcto.