Open Source · Ata
Turbine seu plugin WordPress.
Com a estrutura MVC-S.
O ATA ajuda quem desenvolve plugins WordPress a manter bases de código em crescimento organizadas e fáceis de manter, usando o padrão de projeto MVC.
Para quem desenvolve plugins WordPress
Um lugar para cada coisa.
O ATA dá a todo plugin a mesma estrutura previsível, para que bases de código em crescimento continuem organizadas e fáceis de manter.
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
Os princípios centrais do Ata.
Estruturado por padrão
O ATA oferece uma estrutura de diretórios predefinida que separa de forma lógica as diferentes partes do seu plugin.
Orientado a objetos em primeiro lugar
Ele incentiva escrever código em classes em vez de funções procedurais, melhorando a reutilização e a organização do código.
Separação clara de responsabilidades
Ele implementa uma variação do padrão MVC para manter separadas as camadas de lógica, dados e apresentação.
Roteamento simplificado
O ATA inclui um roteador nativo que torna simples e declarativo registrar endpoints personalizados da REST API ou URLs personalizadas.
Principais diferenças
O que é MVC-S?
O ATA promove uma variação do padrão Model-View-Controller (MVC), que chamamos de MVC-S (Model-View-Controller-Services).
Controller (o motor central)
O Controller é o núcleo do funcionamento do seu plugin. Ele é responsável por tratar as requisições recebidas, registrar todos os hooks e filtros do WordPress e controlar o fluxo da aplicação. Em plugins simples, o Controller pode cuidar de toda a lógica e do acesso a dados diretamente. Em aplicações mais complexas, seu papel evolui para o de um orquestrador: ele chama um Service para a lógica de negócio ou um Model para os dados e depois passa os resultados para uma View renderizar.
View (a camada de apresentação)
A View é uma camada opcional para gerar a saída HTML. Ela recebe os dados do Controller e os renderiza. Uma View deve ter o mínimo de lógica PHP, focando apenas em exibir os dados que recebe.
Model (a camada de dados)
A única responsabilidade do Model é interagir diretamente com o banco de dados. Dentro de uma classe Model, você acessa o objeto de banco de dados do WordPress via $this->db (ex.: $this->db->get_results(...)). Essa camada é opcional; se o seu plugin não interage com o banco de dados, você não precisa dela.
Service (a camada de lógica)
A camada Service é o lugar opcional, mas recomendado para a lógica de negócio central do seu plugin. Quando a lógica fica complexa demais para um Controller, extraia-a para um Service. Assim os Controllers continuam enxutos e focados em tratar requisições.
Plugin de exemplo
Polylang RestAPI Helper
O plugin polylang-restapi-helper é um exemplo perfeito e objetivo do framework ATA.
Como aplicar o MVC do ATA ao seu plugin WordPress
Documentação
Como começar a usar o ATA no seu plugin, de forma rápida e fácil
O ciclo de vida do plugin e o Controller principal
Todo plugin ATA é gerenciado por um Controller central, na raiz. Esse controller principal é o ponto de entrada de todas as funcionalidades do plugin e é responsável por gerenciar o ciclo de vida do plugin.
1. O arquivo principal do plugin (your-plugin-name.php) Este arquivo é bem enxuto. Suas únicas funções são definir as constantes essenciais, carregar o framework ATA e instanciar o seu controller 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. O Controller principal (app/controllers/main-controller.php) Este controller contém a lógica de ativação e desativação e, o mais importante, carrega todos os outros controllers. É aqui que você pode carregar recursos condicionalmente, conforme outros plugins estejam ativos ou não, economizando memória e evitando erros.
// 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 ...
}
}
Adicionando uma página ou aba ao painel administrativo do WordPress
O ATA oferece uma interface fluente para criar facilmente páginas administrativas com várias abas. Isso é gerenciado a partir de um controller.
// 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
}
}
Conectando a um hook do WordPress (Action)
O ATA oferece um prático método auxiliar on() no controller base para registrar action hooks. O construtor ou um método main() do seu controller é o lugar ideal para registrar todos os 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 "";
}
}
Usando filtros do WordPress
Assim como nas actions, você pode usar o método auxiliar filter() para modificar dados.
// 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;
}
}
Adicionando um endpoint à REST API do WordPress
Passo 1: registre a rota em app/routes/main-routes.php. Isso informa ao WordPress que sua URL existe e qual método deve tratá-la.
// 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');
Passo 2: crie uma classe de API em app/apis/ para conter a lógica do 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' => '...']);
}
}
Como funciona o roteamento?
O arquivo de rotas (app/routes/main-routes.php) é um recurso poderoso, mas opcional. Sua única função é atuar como uma central de distribuição, dizendo ao WordPress como tratar certas URLs personalizadas. Se o seu plugin não precisa de URLs personalizadas nem de uma REST API, você não precisa usá-lo.
- Para REST APIs: use o método
api(). Ele registra um novo endpoint em/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 URLs personalizadas no frontend: use o método
page(). Ele cria uma página virtual sem precisar de um post do tipo Página no WordPress.// Registers: example.com/my-custom-url/ $ata_router->page('/my-custom-url')->call('MyPageController::show_page');
Para que servem os diretórios principais opcionais?
app/views
Este diretório guarda seus templates HTML. Ele só é necessário se o seu plugin gera uma interface, como uma página de configurações no admin ou uma página personalizada no frontend. Plugins que só oferecem funcionalidades em segundo plano ou uma REST API provavelmente não terão um diretório views.
models/structures (DTOs)
Este diretório é para Data Transfer Objects (DTOs). Um DTO é uma classe simples usada para definir o formato dos dados que circulam pelo sistema. Este diretório é opcional e pode não ser necessário em muitos plugins. Ele é mais útil quando você precisa impor uma estrutura de dados rígida, principalmente na comunicação com uma API externa.
Sua história de sucesso pode ser a próxima.
Ficou com alguma dúvida? Estamos aqui para ajudar você a tomar a decisão certa.