Ir al contenido
Nibiru docsv0.9.2

¿Por qué Nibiru, no Laravel?

Cinco cosas que Nibiru hace diferente de Laravel y Symfony — cada una respaldada por código real de producción.

Stable Reading time ~ 4 min Edit on GitHub

La mayoría de las comparaciones de frameworks PHP son opiniones personales. Esta es una que se puede buscar con grep.

Los cinco diferenciadores a continuación se extraen de un sitio web real que genera ingresos: maschinen-stockert.de — una plataforma multilingüe de mercado de maquinaria industrial. 36 controladores, 18 módulos, 348 plantillas, 161 migraciones SQL, 37,369 líneas de PHP en dos repositorios. Cada afirmación se vincula a una referencia de archivo:línea dentro de los códigos fuente, por lo que puedes verificarlo.

Si has trabajado con Laravel o Symfony, reconocerás los patrones que Nibiru no tiene. Ese es el punto.


En Laravel, el texto de las páginas reside en archivos Blade ({{ __('page.title') }}) o en un archivo JSON de traducción. Para cambiarlo, un desarrollador edita un archivo y lo despliega. En Nibiru, el texto de las páginas reside en la base de datos, claveado por <controller>/<action> + idioma, y los editores lo actualizan desde la interfaz de administración sin tocar código.

data.maschinen-stockert.de/application/controller/maschineController.php
public function pageAction()
{
$controllerPath = $this->getController() . '/' . $this->getRequest('_action', 'page');
foreach (Cms::init($this->getController())
->loadCmsTemplateTextsByControllerPath($controllerPath, $this->language)
as $t) {
View::assign([
$t['cms_template_texts_text_identifier']
=> $t['cms_template_texts_text_content']
]);
}
}

Efecto neto: las modificaciones de marketing cambian un titular en el editor, refrescan la página y se envían. Sin PR, sin despliegue, sin que el desarrollador esté involucrado. Eso no es un plugin del CMS — el módulo Cms del framework está integrado.

→ Consulte Módulos para ver cómo se compone el módulo del CMS.


2. Los módulos se componen mediante rasgos, no mediante un contenedor de servicios

Sección titulada «2. Los módulos se componen mediante rasgos, no mediante un contenedor de servicios»

La respuesta de Laravel a una clase de 5,000 líneas es los proveedores de servicios e inyección de dependencias. La respuesta de Nibiru es tratos.

El módulo CMS en maschinen-stockert.de está compuesto por 13 rasgos, cada uno con una sola responsabilidad — CmsStore, TextsForm, PageBuilderForm, CmsPageStructureModifier, FormElements, … La clase principal Cms es de 30 líneas que los integra. Agregar una nueva característica es “crear un rasgo, incluirlo, listo.”

application/module/cms/cms.php
class Cms implements Interfaces\Cms, SplSubject
{
use Traits\CmsStore;
use Traits\TextsForm;
use Traits\PageBuilderForm;
use Traits\CmsPageStructureModifier;
use Traits\FormElements;
/ …8 more traits
}

Efecto neto: cero inyección de constructores, cero registro de proveedores de servicios, cero llamadas a bind() / singleton() en un archivo de configuración. Un nuevo desarrollador puede buscar el nombre del trait y ver todos los llamadores.


3. Consulta directa con agregación de JSON, no un ORM

Sección titulada «3. Consulta directa con agregación de JSON, no un ORM»

Eloquent y Doctrine vienen con un costo: cada relación cargada es potencialmente una consulta N+1, y cada agregación insertada en PHP es memoria desperdiciada. Nibiru se apoya en la base de datos donde es fuerte.

-- application/module/machineryscout/traits/machinesElasticSearch.php
SELECT
m.ms_machines_id AS machine_id,
m.ms_machines_name AS machine_name,
JSON_ARRAYAGG(
DISTINCT JSON_OBJECT(
'attribute_name', ma.ms_machine_attributes_attribute_name,
'attribute_value', mav.ms_machine_attribute_values_value,
'attribute_type', ma.ms_machine_attributes_attribute_type
)
) AS attributes,
JSON_ARRAYAGG(DISTINCT mi.ms_machine_images_filename
ORDER BY mi.ms_machine_images_sort_order ASC) AS images
FROM ms_machines m
LEFT JOIN ms_machine_attribute_values mav ON mav.ms_machine_attribute_values_machine_id = m.ms_machines_id
LEFT JOIN ms_machine_attributes ma ON mav.ms_machine_attribute_values_attribute_id = ma.ms_machine_attributes_id
LEFT JOIN ms_machine_images mi ON mi.ms_machines_id = m.ms_machines_id
WHERE m.ms_active = 1
GROUP BY m.ms_machines_id;

Una consulta. Atributos y imágenes agregados en JSON, indexados desde la base de datos. El resultado se alimenta directamente a Elasticsearch, listo para respaldar consultas de rango en dimensiones como “2500 × 1200 mm”.

Efecto neto: Los problemas N+1 no existen. Auditoriable, perfilable, rápido.

→ Consulta Base de Datos y Migraciones para el adaptador Pdo que ejecuta consultas como esta.


4. Control de acceso basado en roles sin cadenas de middleware

Sección titulada «4. Control de acceso basado en roles sin cadenas de middleware»

En Laravel, la autorización es una pila: auth middleware → clase de política → puerta → controlador. En Nibiru, son tres líneas en el constructor:

data.maschinen-stockert.de/application/controller/adminController.php
public function __construct() {
parent::__construct();
$this->user = new User();
$this->acl = new Acl();
$this->acl->init();
$this->user->validate();
}

$this->acl->init() carga el conjunto de roles / permisos para la sesión actual. $this->user->validate() verifica que la sesión esté bien. Si cualquiera falla, la solicitud devuelve la página de inicio de sesión. Las verificaciones por acción ($this->acl->can('edit', 'pages')) se encuentran en las acciones que las necesitan.

El controlador de la API toma un enfoque inverso: una lista blanca de puntos finales públicos en el constructor, autenticación requerida para todo lo demás.

// public endpoints can be listed up-front, auth wraps the rest.
if (in_array($action, ['category', 'machines', 'ollama', 'team'])) {
/ public, skip auth
} else {
$this->user = new User();
$this->acl = new Acl();
$this->acl->init();
$this->user->validate();
}

Efecto neto: la autorización es una expresión que se puede buscar con grep. Sin errores de ordenamiento en el middleware. Sin misterios como “¿por qué este punto final es público?”.

→ Consulte Autenticación para detalles sobre sesiones y ACL.


5. Patrón observador, no despachador de eventos

Sección titulada «5. Patrón observador, no despachador de eventos»

Los eventos de Laravel se propagan mediante un despachador con cierres, oyentes y registros de trabajos en cola. Nibiru utiliza las interfaces estándar de PHP SplSubject / SplObserver. Mismo patrón, dos interfaces, sin capa de abstracción.

class Machineryscout implements IModule, \SplSubject
{
private \SplObjectStorage $observers;
public function attach(\SplObserver $o): void { $this->observers->attach($o); }
public function detach(\SplObserver $o): void { $this->observers->detach($o); }
public function notify(): void {
foreach ($this->observers as $o) $o->update($this);
}
public function indexMachines(): void {
/ …do the work…
$this->notify(); / analytics, cache invalidator, audit log all see it.
}
}

Efecto neto: los cambios de estado son sincrónicos, deterministas y depurables. Sin trabajador de cola. Sin misterio de “¿se disparó el oyente?”. Agrega un observador en el controlador y está conectado.

→ Consulte Módulos para el patrón.


Un desarrollador solitario o un pequeño equipo puede construir y operar una aplicación de producción real —como una que vende maquinaria industrial en 12 países— con menos marcos para aprender, pocas abstracciones para depurar y menos ceremonia por característica. El contratiempo es que si prefieres que el marco oculte cada consulta de base de datos y orqueste cada evento, estarás más feliz en otro lugar.

Si prefieres ver tu código, tómalo.

Lee la presentación →