Skip to content

La lista de campos de un modelo se recarga cuando se actualiza su tabla - #2065

Open
daniel89fg wants to merge 1 commit into
NeoRazorX:masterfrom
daniel89fg:fix-campos-modelo-tabla-actualizada
Open

daniel89fg wants to merge 1 commit into
NeoRazorX:masterfrom
daniel89fg:fix-campos-modelo-tabla-actualizada

Conversation

@daniel89fg

Copy link
Copy Markdown
Contributor

Descripción

Un modelo podía quedarse con una lista de campos obsoleta cuando su tabla se actualizaba después de haber cargado los campos. Los INSERT y UPDATE del modelo omitían entonces las columnas nuevas, sin ningún error.

Se vio con el plugin ConciliacionBancaria, que añade la columna idbankmovement a tablas del core (asientos, recibospagoscli, recibospagosprov). La primera vez que se usaban esos modelos era dentro de una transacción:

  1. DbUpdater::createOrUpdateTable() omite la comprobación de la tabla si hay una transacción abierta («se comprobará después») y no la marca como revisada.
  2. El constructor de ModelClass llama a loadModelFields(), que lee las columnas de la base de datos (todavía sin las nuevas) y las guarda en static::$fields y en la caché (model-fields-<Modelo>).
  3. Más tarde, ya fuera de la transacción, la tabla se actualiza (ALTER TABLE). clearCache() borra model-<Modelo>-*, join-model-* y table-<tabla>-*, pero no model-fields-<Modelo>, y static::$fields sigue en memoria.

En PostgreSQL la consulta fallaba por columna inexistente; en MySQL la columna se creaba, pero el modelo seguía guardando sin ella.

Solución

  • Cuando el constructor comprueba la tabla (queda marcada como revisada), descarta la lista de campos en memoria y en caché antes de loadModelFields(), para leerla de nuevo con la estructura actualizada.
  • loadModelFields() solo guarda la lista de campos en caché si la tabla ya está comprobada. Si la comprobación se omitió por estar en transacción, la lista se queda solo en memoria y se descarta cuando la tabla se compruebe.

Cuando la tabla ya está comprobada (el caso normal) no cambia nada: ni se descarta la caché ni se hacen consultas de más.

Cambios realizados

  • Core/Template/ModelTrait.php: nuevo método protegido clearModelFields() y loadModelFields() no guarda en caché si la tabla no está comprobada.
  • Core/Template/ModelClass.php: declaración abstracta de clearModelFields() y su uso en el constructor tras comprobar la tabla.
  • Test/Core/Template/ModelFieldsTest.php y Test/Core/Template/TestModelFields.php: un modelo de prueba cuya tabla gana la columna email2 después de cargar los campos.
    • Fuera de transacción: tras actualizar la tabla, el modelo ve la columna nueva y la guarda en el INSERT.
    • Dentro de transacción: no se comprueba la tabla ni se guardan los campos en caché; al salir, se actualiza la tabla y se recargan los campos.

Los dos tests fallan sin la corrección.

Cómo probar

  1. Tests: vendor/bin/phpunit --filter ModelFieldsTest.
  2. La batería completa del core pasa en PHP 8.1–8.5 con MySQL y PostgreSQL.

🤖 Generated with Claude Code

Si la tabla se comprobaba en una transacción, DbUpdater la omitía y el
modelo cargaba y guardaba en caché los campos sin las columnas nuevas.
Al actualizar después la tabla, clearCache() no borraba model-fields-*
ni static::$fields, y los INSERT y UPDATE omitían esas columnas.

Ahora el constructor descarta la lista de campos al comprobar la tabla y
loadModelFields() no la guarda en caché mientras la tabla no esté comprobada.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant