Orígenes mixtos usando tablas y vistas

En muchas ocasiones es conveniente enseñar una vista de la BD (VIEW) pero editar o añadir con la tabla original.

Hasta ahora la única manera de conseguir esto era escribiendo un controlador CRUD para la VIEW, que se usaría para listar, otro controlador CRUD para la tabla, que usaría para editar y añadir, usando la capacidad de "editar con una clase diferente".

Este sistema es complicado y tedioso, por lo que se mejorado para facilitar la programación.

Resumen rápido:

  1. Crear un único CRUD.
  2. Crear todo como siempre a partir de una tabla (mejor usando la función auto(), que ya se ocupa de inicializar el schema, table y tableView)
  3. Declarar que se va a usar la VIEW para listar, usando la función auto().

Por ejemplo, si la tabla se llama 'via_operacion_material' y la VIEW 'vista_consumo_material', el código será:

protected function initData()
{
    $this->auto('via_operacion_material');
    $this->auto('vista_consumo_material', null, self::MODE_LST, $this->getSchema());
...

La función auto() antes admitía dos parámetros: el nombre le la tabla o VIEW y el perfil de la base de datos. Ahora admite dos parámetros adicionales:

  1. El primero indica en qué contexto se va a usar la VIEW. self::MODE_LST es una constante que indica el contexto LST, que es el listado inicial que presenta el CRUD.

  2. El segundo es una instancia de la clase Schema, perteneciente a una tabla (en el ejemplo, es el esquema que se fabricó a partir de via_operacion_material) del que se tomará prestada cierta funcionalidad (los índices, la clave primaria y las relaciones).

Eso es todo, el CRUD pasaría a usar la VIEW para listar y la tabla para el resto de operaciones.

Opciones de configuración habituales

A la hora de configurar las etiquetas de los campos o su orden, si se usa $this->tableView->... se estará modificando el TableViewer se que creó para la tabla, no para la vista.

Se han creado métodos de acceso que devuelven uno u otro si se necesita:

$this->getTableView()

Devolverá el tableView usado para la tabla.

$this->getTableView(self::MODE_LST)

Devolverá el tableView usado para la VIEW.

Así, por ejemplo, si se va a configurar las etiquetas de los campos, los mejor será crear un array aparte y asignárselo a ambos (si quieren usarse las mismas, claro):

$etiquetas = [
    'id'           => 'ID',
    'denominacion' => 'Denominación',
    'id_zfx_user'  => 'Usuario',
    ... etc
];

$this->getTableView()->setLabels($etiquetas);
$this->getTableView(self::MODE_LST)->setLabels(etiquetas);

Post-procesado de datos al guardar registro

Se hace sobrecargando la función processPOST(). Puede ser útil usar isUpdate() para saber si es un update o un insert, y también addPostData() y getPostData() para manejar el array $postData sin necesidad de estar descodificando y codificando cadenas.

Ejemplo:

public function processPOST($postData)
{
    if ($this->isUpdate($postData))
    {
        $this->addPostData($postData, 'modificada', true);
    }
    parent::processPOST($postData);
}

Hay que tener en cuenta que hasta que parent::processPOST() no se ejecuta no se actualiza el registro, por si queremos hacer alguna operación posterior que use los datos actualizados. Ejemplo:

public function processPOST($postData)
{
    $oldId = \zfx\PKView::unpack(a($postData, '_id'), 'id');
    parent::processPOST($postData);
    if ($oldId) {
        Modeq::actualizarProgModelo($oldId);
    }
}

Cómo subir fotos y ficheros en general a campos de la BD

Los campos se deben crear como CHARACTER VARYING(512).

Hay que disponer de un lugar donde subir los ficheros, por defecto es en ./res/file-db.

En el controlador Dev hay una función para comprobar los permisos. Se llama dbfiles.

Tanto imágenes como ficheros en general se tratan igual. Dependiendo de uno u otro la previsualización cambia; el resto es exactamente igual.

En el controlador CRUD, hay que convertir los campos a imágenes o a ficheros. Hay una función de ayuda en tableView, para variar, que permite promocionar los campos. Simplemente, si los nombres de las columnas son imagen y manual, el primero una foto y el segundo un PDF, se haría así:

$this->tableView->toImageField('imagen', $this->dbFileUrl);
$this->tableView->toFileField('manual', $this->dbFileUrl);

Todo lo demás es automático. En el ejemplo anterior, $this->dbFileUrl es la URL base de la carpeta donde se almacenarán los ficheros; o sea: http://miurl/res/file-db/

Se usa $this-> porque en el CRUD están definidas las siguientes dos variables: $this->dbFileUrl y $this->dbFilePath que se forma predeterminada se ajustan para que apunten a ./res/file-db pero se pueden personalizar.

Dentro del directorio file-db/ se crean carpetas para las tablas; dentro, subcarpetas para las columnas; y dentro, se almacenan los ficheros con un nombre normalizado y conservándose la extensión (si no es extraña).

Por lo tanto para cada controlador CRUD se podría definir una carpeta (y una URL) diferente y tener una base de datos de ficheros distribuida.

Ocultando y desactivando campos

Campos ocultos

Esta es la forma más potente de ocultar un campo. Su efecto es que no aparece a todos los efectos, como si no existiera. Se hace usando xxxHideFields. El mejor lugar es initData().

OJO porque incluso aunque se forzara alguno desde defaultRS, seguiría sin aparecer y sin guardarse su información.

Ejemplo:

$this->lstHideFields = array('id_srv_operario', 'fechaprogramacion', 're_srv_servicio', 're_srv_instalacion');
$this->addHideFields = array('re_srv_servicio', 're_srv_instalacion');
$this->edtHideFields = array('re_srv_servicio', 're_srv_instalacion');

Campos no editables

Los campos no editables son aquellos que aparecen pero no se pueden modificar. Se pueden inicializar (con defaultRS) y, si tenían contenido, ese contenido se conserva.

Una forma de hacerlo es usando nonEditableFields. Ejemplo:

$this->nonEditableFields = array(
    're_srv_servicio',
    're_srv_instalacion',
    'fechaprogramacion',
    'id_srv_operario'
);