Skip to content

Releases: osumionline/framework

9.12.1 - Soporte para CURRENT_TIMESTAMP en DATETIME

Choose a tag to compare

@osumionline osumionline released this 14 Oct 15:54
Immutable release. Only release title and notes can be modified.

Osumi Framework 9.12.1

Esta versión añade soporte para CURRENT_TIMESTAMP como valor por defecto dinámico de campos DATETIME en el ORM.

CURRENT_TIMESTAMP

Ahora puede definirse un campo DATETIME así:

#[OField(
	type: OField::DATETIME,
	nullable: false,
	default: OField::CURRENT_TIMESTAMP
)]
public ?string $joined_at = null;

Al generar el esquema SQL, se conserva correctamente como:

`joined_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP

En runtime, el ORM resuelve OField::CURRENT_TIMESTAMP al timestamp actual en formato Y-m-d H:i:s cuando aplica los valores por defecto de un nuevo modelo.

generateModelFromDB

generateModelFromDB reconoce ahora las dos representaciones habituales de MariaDB:

CURRENT_TIMESTAMP
CURRENT_TIMESTAMP()

Ambas se generan en el modelo como:

default: OField::CURRENT_TIMESTAMP

Esto permite importar correctamente esquemas reales que utilicen DEFAULT CURRENT_TIMESTAMP en columnas DATETIME.

Validación estricta

OField::CURRENT_TIMESTAMP solo puede utilizarse con campos OField::DATETIME.

Además, se diferencia expresamente del string literal:

'CURRENT_TIMESTAMP'

por lo que un valor textual con ese contenido no se interpreta como una expresión SQL.

Las demás expresiones SQL dinámicas no soportadas, como UUID(), continúan rechazándose explícitamente.

Migración

Esta versión no añade un nuevo paso automático de migración.

Los proyectos que ya utilizan 9.12.0 pueden actualizar directamente mediante Composer:

composer update osumionline/framework --with-dependencies

Después de actualizar puede volver a ejecutarse:

php of generateModelFromDB

9.12.0 - Soporte nativo de DATE, DATETIME y BIGINT en el ORM

Choose a tag to compare

@osumionline osumionline released this 14 Oct 14:49
Immutable release. Only release title and notes can be modified.

Osumi Framework 9.12.0

Esta versión amplía el ORM de Osumi Framework con soporte nativo para columnas SQL DATE, DATETIME y BIGINT, además de reforzar el sistema de migraciones del framework.

DATE y DATETIME

Hasta Osumi Framework 9.11, OField::DATE representaba realmente una columna SQL DATETIME.

A partir de 9.12 ambos tipos quedan separados:

OField::DATE     → SQL DATE      → PHP ?string → Y-m-d
OField::DATETIME → SQL DATETIME  → PHP ?string → Y-m-d H:i:s

Los valores temporales se validan ahora de forma estricta, rechazando fechas u horas imposibles.

Los atributos automáticos #[OCreatedAt], #[OUpdatedAt] y #[ODeletedAt] continúan representando timestamps completos y utilizan internamente DATETIME.

El método OModel::get() y el pipe date de las plantillas admiten ambos tipos temporales.

BIGINT

Se añade el nuevo tipo:

OField::BIGINT

Las columnas BIGINT se representan mediante propiedades PHP ?int y requieren un entorno PHP de 64 bits.

BIGINT también puede utilizarse como clave primaria mediante #[OPK], incluido autoincremento.

No se soportan columnas BIGINT UNSIGNED ni el modificador ZEROFILL.

generateModelFromDB

generateModelFromDB reconoce ahora correctamente:

DATE     → OField::DATE
DATETIME → OField::DATETIME
BIGINT   → OField::BIGINT

Las columnas SQL TIMESTAMP continúan rechazándose al no poder representarse fielmente mediante la semántica DATETIME del ORM.

Migración automática desde versiones anteriores

La versión 9.12.0 incluye un nuevo paso de migración.

Como OField::DATE significaba DATETIME antes de 9.12, los modelos existentes se actualizan automáticamente:

OField::DATE

pasa a:

OField::DATETIME

La migración actúa únicamente sobre referencias PHP reales dentro de src/Model/, conservando comentarios y cadenas de texto.

No se modifica el esquema de la base de datos: los campos existentes mantienen su semántica DATETIME.

Después de la migración, los nuevos usos de OField::DATE representan columnas SQL DATE reales.

Nuevo estado persistente de migraciones

El estado autoritativo del sistema de migraciones deja de almacenarse en:

ofw/tmp/state.json

y pasa a:

.ofw-migrations.json

en la raíz del proyecto.

Este archivo debe versionarse junto con el código de la aplicación.

Para mantener la compatibilidad con proyectos existentes, durante la primera actualización el runner puede seguir leyendo el antiguo ofw/tmp/state.json cuando .ofw-migrations.json todavía no existe.

Este cambio evita que una limpieza de ofw/tmp/ pueda provocar accidentalmente la repetición de una migración ya ejecutada.

Actualización

La actualización puede realizarse normalmente mediante Composer:

composer update osumionline/framework --with-dependencies

La migración 9.12.0 se ejecutará automáticamente cuando corresponda.

Después de actualizar, revisa los modelos modificados y añade .ofw-migrations.json al repositorio de la aplicación.

9.11.0 - Soporte nativo de campos DECIMAL exactos en el ORM

Choose a tag to compare

@osumionline osumionline released this 14 Oct 09:11
Immutable release. Only release title and notes can be modified.

Osumi Framework 9.11.0

Osumi Framework 9.11.0 incorpora soporte nativo para campos SQL DECIMAL(p,s) en el ORM, manteniendo los valores decimales exactos durante todo su ciclo de vida y evitando conversiones intermedias a punto flotante.

Novedades

Soporte nativo para DECIMAL

Se añade el nuevo tipo:

OField::DECIMAL

Los campos DECIMAL deben representarse siempre mediante propiedades PHP ?string:

#[OField(
	type: OField::DECIMAL,
	precision: 12,
	scale: 2,
	nullable: false
)]
public ?string $amount = null;

Los valores se mantienen como cadenas exactas y nunca se convierten a float.

La configuración predeterminada es:

  • precision: 10
  • scale: 2

Los límites soportados son:

  • precisión: 1 a 65
  • escala: 0 a 30
  • scale nunca puede ser mayor que precision

Normalización decimal

El ORM acepta tanto . como , como separador decimal de entrada:

"12"    → "12.00"
"12.5"  → "12.50"
"12,5"  → "12.50"
"-0,50" → "-0.50"

La representación interna utiliza siempre . y conserva una escala fija.

No se admiten:

  • valores float o int;
  • notación exponencial;
  • separadores de miles;
  • valores que requieran redondeo automático.

Los valores que superen la precisión o escala configuradas producen un error.

Consultas tipadas según el esquema

Las condiciones utilizadas por where() y count() se validan y normalizan ahora utilizando la definición del campo en el modelo.

Por ejemplo:

Payment::where([
	'amount' => '12,5'
]);

utiliza internamente:

12.50

mientras que utilizar un float para un campo DECIMAL es rechazado:

Payment::where([
	'amount' => 12.5
]);

También se rechazan condiciones que hagan referencia a campos inexistentes en el modelo.

Soporte en los generadores

Los comandos de generación del framework soportan ahora campos DECIMAL:

  • generateModel
  • generateModelFrom
  • generateModelFromDB

generateModelFromDB conserva la precisión, la escala y los valores predeterminados de columnas DECIMAL como cadenas exactas.

Esto permite realizar correctamente el recorrido:

MariaDB / MySQL
→ modelo Osumi Framework
→ SQL generado

sin convertir los valores decimales a punto flotante.

Restricciones

OField::DECIMAL está disponible exclusivamente para #[OField].

No puede utilizarse en campos #[OPK].

Los parámetros precision y scale tampoco pueden utilizarse con otros tipos de OField.

Compatibilidad con PHP 8.5

Se corrige además la inicialización del esquema ORM para comprobar ReflectionProperty::hasDefaultValue() antes de llamar a ReflectionProperty::getDefaultValue().

Esto evita el aviso deprecado de PHP 8.5 al procesar propiedades que no tienen un valor predeterminado explícito.

Compatibilidad

La actualización desde Osumi Framework 9.10.2 es compatible hacia atrás.

Los proyectos existentes que no utilicen OField::DECIMAL no necesitan modificar sus modelos.

No existe ningún paso automático de migración para esta versión.

9.10.2 - Corrección del binding tipado de parámetros PDO en el ORM.

Choose a tag to compare

@osumionline osumionline released this 12 Oct 10:49
Immutable release. Only release title and notes can be modified.

Osumi Framework 9.10.2 es una versión de mantenimiento que corrige el binding de parámetros del ORM al ejecutar sentencias preparadas con PDO.

Corrección

  • Los valores bool se bindean ahora mediante PDO::PARAM_BOOL.
  • Los valores int utilizan PDO::PARAM_INT.
  • Los valores null utilizan PDO::PARAM_NULL.
  • El resto de valores escalares soportados utilizan PDO::PARAM_STR.
  • La corrección se aplica de forma consistente a consultas, conteos, inserciones, actualizaciones y eliminaciones realizadas por OModel.

Esto evita, entre otros casos, que valores booleanos como false puedan llegar a MySQL/MariaDB como una cadena vacía y provocar errores en columnas TINYINT(1) cuando se utiliza modo estricto.

Migración

No es necesario realizar ningún cambio en las aplicaciones existentes y esta versión no añade ningún nuevo paso automático de migración.

.10.1 - Corrección para emisión de códigos HTTP establecidos manualmente

Choose a tag to compare

@osumionline osumionline released this 03 Oct 21:30
Immutable release. Only release title and notes can be modified.

Osumi Framework 9.10.1

Patch release que corrige la emisión de códigos HTTP establecidos manualmente mediante OCore::setHttpStatus().

Desde la introducción del pipeline de Middlewares en 9.9, el emisor final toma el código HTTP desde el estado interno de OMiddleware. setHttpStatus() seguía actualizando únicamente el estado interno de OCore, por lo que determinados componentes podían generar el cuerpo de error correcto y terminar enviando HTTP 200.

En 9.10.1:

  • OCore::setHttpStatus() sincroniza el código con OMiddleware.
  • Se restaura el comportamiento histórico de la API pública.
  • Los Middlewares posteriores pueden seguir sobrescribiendo explícitamente el status.
  • Se añade cobertura de regresión end-to-end.

No requiere cambios en aplicaciones existentes ni pasos automáticos de migración.

9.10.0 - Soporte para respuestas HTTP por streaming

Choose a tag to compare

@osumionline osumionline released this 03 Oct 17:24
Immutable release. Only release title and notes can be modified.

Osumi Framework 9.10.0

Osumi Framework 9.10.0 incorpora soporte nativo para respuestas HTTP por streaming, pensado para servir archivos grandes o contenido generado progresivamente sin cargar el cuerpo completo en memoria.

OStreamResponse

Se añade OStreamResponse, una nueva respuesta HTTP basada en un stream PHP legible.

Permite configurar:

  • cabeceras HTTP;
  • código de estado;
  • tamaño de bloque de lectura;
  • cierre automático del recurso.

Los streams administrados por el framework se cierran al finalizar, al descartarse la respuesta o al destruirse el objeto.

Componentes streaming

Los componentes pueden devolver directamente un OStreamResponse desde run():

public function run(): OStreamResponse

También se admiten las variantes con ORequest y DTO:

public function run(ORequest $req): OStreamResponse
public function run(MyDTO $dto): OStreamResponse

Cuando run() declara explícitamente OStreamResponse, el componente puede omitir su archivo de plantilla.

Una respuesta streaming no puede anidarse dentro de otro componente ni convertirse a string.

Integración con Middlewares

Las respuestas streaming mantienen el pipeline de Middlewares.

El flujo es:

before
↓
Componente
↓
OStreamResponse
↓
afterRender
↓
afterResponse
↓
Cierre de conexiones de base de datos
↓
Cabeceras HTTP
↓
Emisión del stream por bloques

No se envía ningún byte del stream hasta que afterRender y afterResponse han terminado.

Durante estas fases:

$data['is_streaming_response'] === true

Los Middlewares pueden modificar contexto, cabeceras y estado HTTP o detener la respuesta antes de comenzar la emisión.

No pueden sustituir body en una respuesta streaming, ya que no existe un cuerpo completo materializado en memoria.

Layouts

Los layouts se omiten automáticamente para respuestas OStreamResponse.

Las respuestas tradicionales basadas en plantillas mantienen exactamente el comportamiento anterior.

Gestión de recursos

La emisión se realiza por bloques, con un tamaño predeterminado de 1 MiB, evitando cargar archivos completos en memoria.

Antes de comenzar una descarga potencialmente larga, el framework libera las conexiones de base de datos que ya no son necesarias.

Si un Middleware detiene la petición antes de la emisión:

  • el stream se descarta;
  • no se envía ningún byte;
  • se restauran las cabeceras normales;
  • se genera la respuesta de error habitual.

También se han añadido validaciones para streams no legibles, cabeceras HTTP inválidas, códigos de estado y tamaños de bloque incorrectos.

Compatibilidad

9.10.0 es compatible hacia atrás con 9.9.1.

No requiere cambios en aplicaciones existentes y no añade ningún paso automático de migración.

Las respuestas tradicionales, componentes con plantilla, layouts y Middlewares existentes continúan funcionando sin cambios.

Documentación

La documentación se ha actualizado en:

  • castellano;
  • inglés;
  • euskera;
  • documentación específica para LLM;
  • llms.txt;
  • guía de migración 9.9.1 → 9.10.0.

9.9.1 - Corrección en la detección de rutas con Middlewares durante las migraciones

Choose a tag to compare

@osumionline osumionline released this 02 Oct 09:37
Immutable release. Only release title and notes can be modified.

Osumi Framework 9.9.1 es una versión de mantenimiento que corrige un problema en el sistema de migraciones automáticas introducido en 9.9.0.

Corrección

  • Se mejora la detección de rutas que ya utilizan Middlewares mediante OMiddleware::PHASE_BEFORE, OMiddleware::PHASE_AFTER_RENDER y OMiddleware::PHASE_AFTER_RESPONSE.
  • Estas rutas ya no se interpretan incorrectamente como definiciones legacy de Filters durante la migración.
  • Se añade cobertura de tests para este caso.

Migración

No hay cambios de API ni acciones necesarias por parte del usuario.

La versión 9.9.1 no añade un nuevo paso de migración; el último paso sigue siendo 9.9.0.

9.9.0 - Nuevo sistema de Middlewares y migraciones automáticas de proyectos.

Choose a tag to compare

@osumionline osumionline released this 02 Oct 07:49
Immutable release. Only release title and notes can be modified.

Osumi Framework 9.9.0

Osumi Framework 9.9.0 incorpora un nuevo sistema nativo de Middlewares, sustituye la arquitectura anterior de Filters e introduce un motor de migraciones automáticas de proyectos integrado con Composer.

Se trata de una versión importante con cambios incompatibles para aplicaciones que utilicen Filters, pero incluye una migración automática diseñada para conservar su lógica actual mediante adaptadores de compatibilidad.

Middlewares

El nuevo pipeline permite ejecutar Middlewares en tres fases:

  • before: antes de ejecutar el componente.
  • afterRender: después de renderizar el componente y antes del layout.
  • afterResponse: después de generar la respuesta final y antes de enviarla.

Los Middlewares pueden configurarse a nivel:

  • global
  • grupo
  • ruta

En cada fase se ejecutan en este orden:

global
→ grupo exterior
→ grupo interior
→ ruta

Un Middleware puede:

  • publicar contexto;
  • modificar el cuerpo de la respuesta;
  • añadir o sustituir cabeceras;
  • cambiar el código de estado HTTP;
  • detener el pipeline mediante stop;
  • devolver errores tipados según el tipo de respuesta.

Los Middlewares globales se configuran en:

src/Middleware/Middlewares.php

Contexto de Middleware

ORequest incorpora:

$req->getMiddleware('Login');
$req->getMiddlewareValue('Login', 'id');

Los DTO también pueden utilizar contexto de Middleware como origen explícito:

#[ODTOField(
	required: true,
	middleware: 'Login',
	middlewareProperty: 'id'
)]
public ?int $idUser = null;

Esto permite utilizar valores de confianza generados en servidor, como el ID del usuario autenticado, sin aceptar sustituciones desde los parámetros enviados por el cliente.

Filters

Los Filters dejan de formar parte del runtime de Osumi Framework.

El código nuevo debe utilizar Middlewares.

También se elimina la creación de nuevos Filters mediante la CLI:

php of add --option middleware --name Login

es ahora la forma recomendada de generar este tipo de lógica transversal.

Migraciones automáticas

9.9.0 incorpora un sistema de migraciones versionadas para actualizar proyectos cuando cambia la API del framework.

El paquete expone:

php vendor/bin/ofw-migrate

con soporte para:

  • --from
  • --to
  • --dry-run
  • --force
  • --verbose
  • --no-interaction
  • --help

El estado se almacena en:

ofw/tmp/state.json

Las migraciones son idempotentes y los cambios se aplican de forma transaccional, con copias de seguridad y rollback automático en caso de error.

Integración con Composer

El nuevo sistema se integra con:

osumionline/plugin-updater

Durante una actualización mediante Composer, el plugin detecta la versión instalada y ejecuta automáticamente las migraciones pendientes después de regenerar el autoloader.

La aplicación debe autorizar el plugin en su composer.json:

{
	"config": {
		"allow-plugins": {
			"osumionline/plugin-updater": true
		}
	}
}

También están disponibles:

OFW_DRY_RUN
OFW_FORCE
OFW_VERBOSE

Migración automática de Filters

El paso de migración 9.9.0:

  • detecta Filters antiguos bajo src/Filter/;
  • conserva sus archivos y su lógica original;
  • genera adaptadores *Middleware.php;
  • transforma rutas con Filters a Middlewares before;
  • cambia getFilter() por getMiddleware();
  • cambia filter / filterProperty de DTO por middleware / middlewareProperty;
  • crea src/Middleware/Middlewares.php si no existe.

La migración realiza primero un preflight completo y se detiene ante construcciones ambiguas que no pueda transformar de forma segura.

Entre los casos que requieren intervención manual están:

getFilters()
setFilter()
setFilters()

y las expresiones dinámicas de Filters utilizadas en rutas.

Semántica de stop

stop tiene la misma semántica en las tres fases.

  • En before, evita ejecutar el componente y el layout.
  • En afterRender, evita aplicar el layout.
  • En ambos casos, afterResponse sigue ejecutándose.
  • En afterResponse, detiene los Middlewares restantes de esa fase y sustituye la respuesta final por el error tipado.

Los Middlewares afterResponse pueden inspeccionar el estado de errores producidos en fases anteriores.

Robustez y compatibilidad con PHP 8.5

Durante el desarrollo de 9.9 se ha realizado una auditoría amplia del framework, incluyendo mejoras en:

  • tipado y contratos internos;
  • routing y normalización;
  • DTOs y ORequest;
  • sesiones y ejecución CLI;
  • ORM;
  • configuración;
  • manejo de errores;
  • filesystem y operaciones temporales;
  • validaciones de firmas de componentes;
  • compatibilidad con PHP 8.5;
  • eliminación de avisos deprecados.

También se corrigió OColors para evitar el uso de null como índice de array en PHP 8.5.

Nuevo skeleton

El repositorio osumionline/new ha sido actualizado para crear directamente proyectos 9.9 nativos:

  • utiliza src/Middleware/;
  • incluye Middlewares.php;
  • los ejemplos usan Middlewares nativos;
  • ya no incluye Filters;
  • requiere osumionline/framework ^9.9.0.

Documentación

La documentación se ha actualizado en:

  • inglés;
  • castellano;
  • euskera.

Incluye:

  • concepto completo de Middlewares;
  • routing, DTOs, components, layouts, services y CLI;
  • quickstart y recipes;
  • documentación específica para LLM;
  • llms.txt;
  • guía completa de migración 9.8.5 → 9.9.0.

Compatibilidad

9.9.0 es incompatible a nivel de API con el antiguo runtime de Filters.

La migración automática proporciona un puente para proyectos existentes, pero los adaptadores generados están pensados como compatibilidad temporal.

Para nuevo desarrollo se deben utilizar siempre Middlewares nativos.

9.8.5 - Cambios en firma de métodos run de componentes. Nuevo pipe plain.

Choose a tag to compare

@osumionline osumionline released this 26 Sep 21:59
Immutable release. Only release title and notes can be modified.

Osumi Framework 9.8.5

Esta versión incorpora mejoras en la ejecución de componentes y amplía las posibilidades de las plantillas con un nuevo pipe.

Novedades

  • Nuevas firmas para run() en componentes

    • Los componentes ahora pueden definir run() sin parámetros.
    • Se admiten explícitamente estas tres formas:
      • run(): void
      • run(ORequest $req): void
      • run(MyDTO $dto): void, donde MyDTO extiende ODTO.
    • Las firmas no compatibles se detectan y rechazan automáticamente.
  • DTO independientes del namespace

    • La detección de DTO ya no depende de que estén ubicados en un namespace concreto.
    • Cualquier clase que extienda ODTO puede utilizarse directamente como parámetro de run(), independientemente de dónde esté ubicada dentro de la aplicación.
  • Nuevo pipe plain

    • Se añade el pipe plain para utilizar cadenas de texto sin aplicar urlencode().
    • La salida se genera de forma segura para JSON, escapando correctamente comillas y otros caracteres especiales.
    • Los caracteres Unicode y las barras se conservan sin escapar.
    • Los valores null se mantienen como null.

Compatibilidad

Los componentes existentes que utilizan run(ORequest $req) o DTO que extienden ODTO continúan funcionando sin cambios.

El pipe string mantiene su comportamiento actual basado en urlencode(), por lo que plain se incorpora como una nueva alternativa sin modificar el comportamiento existente.

Documentación

La documentación del framework se ha actualizado en castellano, inglés y euskera para reflejar:

  • Las nuevas firmas admitidas por run().
  • La detección de DTO mediante herencia de ODTO.
  • El nuevo pipe plain.
  • La nueva guía de migración de 9.8.4 a 9.8.5.
  • La documentación específica para LLM y llms.txt.

9.8.4 - Anidamiento con prefix y group y nuevo caso 401 para HttpStatus

Choose a tag to compare

@osumionline osumionline released this 26 Sep 10:40
Immutable release. Only release title and notes can be modified.

Esta nueva versión trae una corrección y una mejora.

Corrección en getHttpStatus()

Se ha incorporado el caso 401 Unauthorized. Antes al intentar devolver este estado no lo reconocía y acababa devolviendo un HttpStatus 200.

Mejora en rutas

Se han mejorado los métodos estáticos ORoute::prefix y ORoute::group para permitir anidamiento. Ahora al hacer esto:

ORoute::prefix('/api', function(): void {
  ORoute::get('/health', HealthComponent::class);

  ORoute::prefix('/admin', function(): void {
    ORoute::post('/login', LoginComponent::class);
    ORoute::get('/me', MeComponent::class, [AdminAuthFilter::class]);
  });
});

Se generan las siguientes rutas correctamente:

  • /api/health
  • /api/admin/login
  • /api/admin/me

Además se ha añadido una normalización a todas las URLs creadas para evitar problemas con barras:

ORoute::prefix('/api/', function(): void {
  ORoute::prefix('//admin///', function(): void {
    ORoute::get('//users/', UsersComponent::class);
  });
});

Generará correctamente:

  • /api/admin/users

Esta normalización se ha añadido en todos los métodos estáticos de ORoute: get, post, put, delete, view, group y prefix