alvaro-prieto
4/27/2017 - 10:53 AM

CRUD PHP (carga lista añadeFiltro, inserta, borra, modifica, apilaEstado,carga , orden, count cuenta, insertar, borrar, modificar)

Acceso a datos y generalidades (métodos comunes: lista añadeFiltro, listaExpandida, apilaEstado,carga , orden, count cuenta insertasinoexiste) mas keywords: cargar ordenar contar filtrar filtro CRUD

CRUD (quid3)

En QUID las entidades de clases están mapeadas con tablas de base de datos.

Si la función en la que estamos está definida dentro de una clase, podemos acceder a la misma a través de $this->

Por convenio, utilizamos el nombre de variable igual al nombre de la clase:

$PersonalBanners = new PersonalBanners();


INSERTAR

Lo chulo del inserta, es que al mismo tiempo carga. Si insertas, podrás acceder a campos a través de la clase actual:

$MiClase->datos->nombreCampo

Otro ejemplo:

$PersonalBanners->inserta([     //listado de campos de la tabla a insertar
        "idCentro"=> $this->quid->idcentro() , 
        "nombre"=> 'Boletín qPersonal'
    ]);

Inserción únicamente si no existe

insertaSiNoExiste( [filtro para saber si existe], [requeridos de inserción adicionales]);

$tipoMatricula = $this->WebexTipoMatricula->insertaSiNoExiste(
  ["idactividad"=>$this->id, "global"=>'1'],
  ["tipomatricula"=>"Precio global"]
);

De esta manera, si el registro existe se obtiene, y si no existe, se inserta y se retorna. Aun no lo he usado mucho para saber con detalle como funciona, pero sospecho que el campo de filtro inicial se inserta sin necesidad de especificarlo en los requeridos de inserción

Breve ejemplo más extenso y mezclado:

$libros=new Libros($this->quid);
$libros->añadeFiltro("year(fecha)=2011"); //Selecciona los libros de un año determinado.
$libros->orden("paginas"); //Ordenados por tamaño
$libros->orden("paginas DESC"); //orden ordenacion inverso descenciente desc
$libros->agrupacion("autor"); //Agrupados por autor (sólo obtendremos un libro para cada autor)
$libros->limite(20); //Limitando a 20 resultados
$listado=$libros->lista(); //Obtiene un array con 20 libros (un por autor) del año 2011 y ordenados por nº de páginas
$ids = $libros->listaIds(); //Obtiene un array con los ids de los elementos
// a veces se utiliza para sacar un where in:
whereIn($Centro->listaIds()) //  --> "('200','201','203')" util para cuando queremos hacer un in
$total = $libros->cuenta() //Devuelve el nº de registros del resultset (creo)

CARGAR

$this->carga(5);  //utiliza el id obviamente
REGISTRO CARGADO Y ACCESO A DATOS

Cuando está cargado (ya sea $this o $MiClase), podemos acceder a los datos de las siguientes maneras:

  • $this->id (especial para el caso del campo id)
  • $this->datos->id o $this->datos->miCampo (forma normal)
  • $this->registro Alternativamente, podemos acceder a todo el array (registro)
  • $this->registro["miCampo"] o a un campo concreto del registro

Entiendase el registro como un array, una fila entera de la base de datos. A veces es más util trabajar así, otras veces con $this->datos

Si un registro tiene id, es que está cargado. Se puede utilizar para saber si se ha hecho una inserción correctamente, etc.

CARGAR con WHERE

Cargar con una especie de where, util para cuando sabemos que hay un unico resultado

$this->carga([ "nombre" => "juan", "sexo" => "masculino" ]); 

Si hubiera multiples, carga unicamente el primero.

Una vez cargado un registro, se accede a los datos a traves de $this->datos, excepto el ID que si queremos está disponible directamente a través de $this->id

$ejemplo = $this->datos->nombre;
$idActual = $this->id;

También se puede hacer un carga en una instancia de una clase (sin usar this):

$libros=new Libros();
$resultado=$libros->carga(134);

También se puede hacer un carga pasandole un filtro (nótese que $parametros es el objeto a través del que quid3 pasa los parámetros de entrada de una función)

$ApiFunciones->carga([
  "clase" => $parametros["clase"],
  "funcion" => $parametros["funcion"]
]);

Conviene saber si un objeto se ha cargado correctamente, la forma más estandar es comprobando si: $resultado->id o si $resultado->datos->id

$libros=new Libros();
$resultado=$libros->carga(134);
if ($resultado->id){
    echo "Sí se ha seleccionado el objeto";
}else{
    echo "No existen ningún registro con clave principal 134";
}

MODIFICAR

$this->modificaDato('nombre_campo',69);  
//siendo $this el objeto cargado y  69 el valor a actualizar

también está la opción que guarda muchos datos en vez de uno solo, que va con array

$this->modificaDatos([
  "idPersonalReconocimiento" => $insercion["id"],  
  "campo2" => $valor2
]);

LISTAR (lista simple)

Retorna el conjunto de registros que cumplen una condición. Conviene tener cuidado para no pedir demasiados datos

$this->lista();  //OJO! es como hacer un select *
$this->lista("nombre, apellidos"); //forma correcta: especificar las columnas que queremos
$this->listaUno(); //lo mismo pero solo retorna uno, con la ventaja de que no hay que acceder a [0]
$this->cuenta();  //es un count tras un lista (sobre un objeto cargado)

En una lista también podemos acceder a campos de tablas asociadas, mediante lo que en qInnova denomicamos "expansión". Expandir es ir de una tabla a otras para obtener cruces.

Nótese que para acceder a campos expandidos (utilizando lista(), las tablas involucradas han de estar en la relación, y cada una de ellas podrá tener sus propios filtros aplicados:

$MisAutores=new MisAutores();
$MisAutores->MisLibros->MisCapitulos->lista(
  "MisAutores.nombre,
  MisAutores.id,
  titulo"); //como este campo es de la última tabla encadenada, no hace falta indicarla

LISTAR (listas más avanzadas)

  • LISTA UNO : permite obtener un único registro. Tiene la ventaja de que no tendremos que acceder a los resultados[0]["fechamaxima"], sino que nos saltamos el primer nivel:
$fechas= $webex_alumno->WebexMatriculas->Webex->listaUno(
  'min(fechainicio) as fechaminima,max(fechafin) as fechamaxima'
);
  • LISTA AGRUPADA :

La lista agrupada, retorna un conjunto de registros/filas indexando aquellas que tengan un campo en común. Ese campo, será la key primaria del array, quedando los registros como arreglos anidados agrupados.

El primer parámetro al invocar a la función listaAgrupada() son los campos que queremos por cada registro, y el segundo, el campo agrupador en el array primario.

NOTA : Es importante que el campo agrupador esté también en la query.

$lista = $PersonalLogros->PersonalLogrosUsuarios->listaAgrupada(
  "id, PersonalLogros.logro,PersonalLogros.tipo", //campos por fila
  "tipo" //campo indexador (aplanador)
);

LISTA EXPANDIDA

Quizás sea la forma más útil para listar registros. Especialmente útil cuando queremos extraer datos de otras tablas relacionadas que se ramifican, sin tener que cruzarlas en la relación inicial (a la izquierda). Tiene la peculiaridad de que cuando hay muchos registros asociados a una fila, se concatenan con coma.

Pequeño vídeo explicativo: Explicación de Santiago

IMPORTANTE: La lista expandida siempre empieza desde la clase en la que queremos que haya un registro por fila.

¿Esto que significa?

Que MisLibros->lista() tendrá el mismo numero de líneas que MisLibros->listaExpandida(....) por mucho que se cruce con otras cosas en las expansiones.

La clase de inicio (antes de invocar a la función) es la que queremos que tenga un registro por fila

  • Tener en cuenta que nunca hay que escribir la clase de inicio en los campos, ni en los derivados. Si en este caso HumbPreguntasOpciones se relaciona con HubPreguntas, podemos poner HubPreguntas directamente.
  • Si un campo tiene multiples registros, se agrupan automáticamente por comas, fijarse en el campo idConector
  • En una lista expandida, se pueden aplicar filtros sobre la clase actual o cualquiera de las anteriores.
$listado = $this->HubPreguntasOpciones->listaExpandida("
  id as id, //superfluo
  HubPreguntas.id as idPregunta, 
  HubPreguntas.pregunta as pregunta, 
  opcion as opcion, 
  id as idOpcion, 
  HubPreguntasConectores.id as idConector
");

Resultado (truncado). Observar que cuando hay más de un elemento expandido de una clase relacionada, su valor se concatena con ,

array (size=10)
2 => 
  array (size=6)
    'id' => string '2' (length=1)
    'idPregunta' => string '2' (length=1)
    'pregunta' => string '¿Quieres asesoramiento sobre cómo innovar en tu asignatura?' (length=61)
    'opcion' => string 'Sí, pero no sé cómo' (length=22)
    'idOpcion' => string '2' (length=1)
    'idConector' => string '4, 6' (length=4)  // <-- ves! se han unido!
4 => 
  array (size=6)
    'id' => string '4' (length=1)
    'idPregunta' => string '2' (length=1)
    'pregunta' => string '¿Quieres asesoramiento sobre cómo innovar en tu asignatura?' (length=61)
    'opcion' => string 'Sí, sobre aprendizaje activo' (length=29)
    'idOpcion' => string '4' (length=1)
    'idConector' => string '2,4,6' (length=2) // <-- ves! se han unido!

Otro ejemplo, queremos todos los logros obtenidos, ordenados por fecha, con información sobre quien los ha conseguido. Como queremos todos los logros obtenidos, partimos desde esa tabla (la de ocurrencias de logros)

$PersonalLogros = new PersonalLogros();
$logros = $PersonalLogros->PersonalLogrosUsuarios->orden("fecha desc");
$logros = $PersonalLogros->PersonalLogrosUsuarios->listaExpandida("
 PersonalLogros.id as id,
 PersonalLogrosUsuarios.fecha as fecha,
 PersonalLogros.logro as logro,  
 PersonalLogros.descripcion as descripcion,
 PersonalLogrosUsuarios.Usuario.nombre as nombre,
 PersonalLogrosUsuarios.Usuario.apellidos as apellidos
");

ORDEN

Permite ordenar por una columna antes de hacer un lista

$this->orden("nombre");  

AÑADIR FILTROS

Se pueden aplicar filtros (condiciones SQL) en distintos niveles de una relación entre clases, se aplicarán a la hora de hacer el próximo lista:

En este caso, elegir solo las filas cuyo titulo empiece por la letra 'E' aunque también se pueden poner ands y otros wheres complejos. Los filtros sobre clases anteriores se encadenan.

$this->añadeFiltro("id=5");
$this->SoporteUsuariosAplicaciones->SoporteColaboradores->añadeFiltro("activo=1");
$this->añadeFiltro("left(titulo,1)='E'");

Otro ejemplo:

$Webex->añadeFiltro("idcentro = '5' and firma_electronica = '0' and horas_lectivas = '10.00' ");

ElIMINAR FILTROS

$this->borraFiltro();

SCOPE DE FILTROS, APILAMIENTO Y DESAPILADO:

Podemos trabajar con scopes de filtros que solo tienen validez dentro de su ámbito comprendido entre apilaEstado()y desapilaEstado(). Siempre hay que intentar que al final de un código, sobre todo si aplica a $this, el filtro quede como estaba.

$SoporteColaboradores = new SoporteColaboradores();
$SoporteColaboradores->apilaEstado();
$SoporteColaboradores->añadeFiltro("nombre='Alicia'");
$SoporteColaboradores->añadeFiltro("apellidos='Hernandez'");
$listado = $SoporteColaboradores->lista("id,nombre,apellidos");
//var_dump($SoporteColaboradores->filtroActual());
//var_dump($listado);
$SoporteColaboradores->desapilaEstado();
//var_dump($SoporteColaboradores->filtroActual());
$listado2 = $SoporteColaboradores->lista("id,nombre,apellidos");
//var_dump($listado2);

Otro ejemplo en el que podemos ver que los filtros se concatenarán automáticamente:

$this->apilaEstado();
$this->añadeFiltro("idusuario_emisor=".$this->quid->idusuario());
$this->añadeFiltro("idusuario_receptor=".$parametros["idUsuarioReceptor"]);
$this->desapilaEstado();

FILTROS y TABLAS POLIMÓRFICAS (obsoleto?)

//$this->relacion("InventariosEquiposInformaticos.idarticulo");
//Esta linea no tendría que ser necesaria, creo que principalmente para tablas polimorficas
$this->InventariosEquiposInformaticos->añadeFiltro("InventariosEquiposInformaticos.id=".$this->datos->id);

CASOS EXTRAÑOS y FALLOS CONOCIDOS

(Al menos aplica a cruces con la clase Archivo). Cuando hay subclases hijas y se hace el cambio del filtro en una hija el apilaEstado no coge el estado de las subclases hijas, por un fallo del framework.

En ese caso se utiliza esto:

$this->eliminaRelacion("Archivo");
//Siendo $this en este caso Webex