Cuando se necesita realizar una consulta y posterior listado, que involucre a varias tablas de una base de datos, puede resultar de utilidad, para ganar en velocidad de procesamiento, utilizar la opción de cargar todos los datos de la consulta en un array multidimensional y luego descargarlo en un archivo CSV o imprimirlo.
Para conocer todas las opciones disponibles de Doctrine y los Data Hydrators, se puede consultar (en inglés), aquí
Yo he necesitado incluir en una consulta el contenido de gran número de tablas (21 en total) de una base de datos, y luego generar un archivo CSV.
Veamos mi ejemplo:
La consulta que necesité hacer, incluida en el archivo actions.class.php tenía la siguiente forma:
public function executeConsultagral(sfWebRequest $request)
{
$records = Doctrine_Core::getTable('AccionConflictiva2')
->createQuery('a')
->leftJoin('a.ActoresAccionConflict3y4 y')
->leftJoin('a.ActoresTa1 at')
->leftJoin('a.FormatosProtestasHasAccionConflictivaT6 h')
->leftJoin('a.FormatosProtestasTa14 f')
->leftJoin('a.DemandasHasAccionConflictivaT5 k')
->leftJoin('a.DemandasTa2 dt')
->leftJoin('a.Conflictos1 c')
->leftJoin('y.TipoOrganizacionTa10 tot')
->leftJoin('y.OrganizacionTa11')
->leftJoin('c.SectorActividadCiuTa7 sac')
->leftJoin('c.SubsectorActividadTa8 sat')
->leftJoin('c.Conflictos1HasActoresTa1 cha')
->leftJoin('c.RelacionConflictualPrincipalTa9 rcp')
->leftJoin('a.FuentePrimariaTa3 p')
->leftJoin('a.FuenteSecundariaTa4 s')
->leftJoin('a.AlcanceTa5 l')
->leftJoin('a.LugaresTa6 u')
->leftJoin('a.RespuestaEstadoTa13 r')
->leftJoin('a.ParticipacionBasesTa12 t')
->leftJoin('a.NivelAgregadoTa15 n')
->where('y.Convocante=2')
->andWhere('a.Marca_patronal<>1')
->andWhere('c.Marca_patronal<>1')
->orderBy('c.Id, a.Id');
$chorizo = $records->execute(array(), Doctrine_Core::HYDRATE_ARRAY);
$this->getUser()->setAttribute('databis', $chorizo);
}
Prestemos atención a las dos últimas líneas de la consulta anterior:
$chorizo = $records->execute(array(), Doctrine_Core::HYDRATE_ARRAY);
$this->getUser()->setAttribute('databis', $chorizo);
Todos los datos de la consulta son cargados en la variable $chorizo que es un array multidimensional. El aspecto del array generado (solo para el primer elemento), se muestra a continuación:
Array
(
[0] => Array
(
[id] => 285
[idconflictos] => 133
[idparticipacion] => 5
[idalcance] => 3
[idlugar] => 2
[fuente_primaria] =>
[fuente_secundaria] => 1
[idnivel_agregado] => 1
[id_respuesta_estado] => 8
[tipo_fuente] => 2. Secundaria
[fecha_fuente] => 2013-01-03
[titulo_nota] => El municipio redujo adicionales de policÃa
[descripcion_situacion] => El gremio denunció falta de servicio por deudas. El Ejecutivo aclaró que el recorte obedece a la menor actividad estival.
[link_diario] => http://www.lavoz.com.ar/politica/el-municipio-redujo-adicionales-de-policia
[descripcion_alcance] => Municipalidad de Córdoba
[marca_patronal] => 0
[ActoresAccionConflict3y4] => Array
(
[0] => Array
(
[actores_ta1_id] => 10
[accion_conflictiva_2_id] => 285
[tipo_organizacion_ta10_id] => 1
[organizacion_ta11_id] => 120
[tipo_actor] => Trabajador
[actor_explicado] =>
[descripcion_organ] =>
[convocante] => 2
[TipoOrganizacionTa10] => Array
(
[id] => 1
[descripcion] => Sindicato
)
[OrganizacionTa11] => Array
(
[id] => 120
[organizacion] => SUOEM (Sind Ú. Obr y Empl Munic) Capital
[protagonista] => 0
[antagonista] => 0
)
)
[1] => Array
(
[actores_ta1_id] => 32
[accion_conflictiva_2_id] => 285
[tipo_organizacion_ta10_id] => 11
[organizacion_ta11_id] => 75
[tipo_actor] => Estado
[actor_explicado] =>
[descripcion_organ] =>
[convocante] => 5
[TipoOrganizacionTa10] => Array
(
[id] => 11
[descripcion] => Estado
)
[OrganizacionTa11] => Array
(
[id] => 75
[organizacion] => Poder Ejecutivo Municipal
[protagonista] => 0
[antagonista] => 0
)
)
)
[ActoresTa1] => Array
(
[0] => Array
(
[id] => 10
[actor] => Trabajadores estatales
)
[1] => Array
(
[id] => 32
[actor] => Estado municipal como empleador
)
)
[FormatosProtestasHasAccionConflictivaT6] => Array
(
[0] => Array
(
[formatos_protestas_ta14_id] => 9
[accion_conflictiva_2_id] => 285
[descripcion] =>
[principal] => 1
)
)
[FormatosProtestasTa14] => Array
(
[0] => Array
(
[id] => 9
[tipo_de_acciones] => Difusión y comunicación
[descripcion] =>
[tipo] => 5
)
)
[DemandasHasAccionConflictivaT5] => Array
(
[0] => Array
(
[demandas_ta2_id] => 7
[accion_conflictiva_2_id] => 285
[descripcion_demanda] => falta de adicionales policiales
[principal] => 1
)
)
[DemandasTa2] => Array
(
[0] => Array
(
[id] => 7
[motivos_o_demandas] => CYMAT no salarial (cond. y medio amb.)
[descripcion] =>
[tipo] => 0
)
)
[Conflictos1] => Array
(
[id] => 133
[id_relacion_conflictual_principal] => 5
[id_sector_actividad] => 12
[demandas_id] => 7
[id_subsector_actividad] => 33
[descripcion_general] => Trabajadores municipales de Córdoba agrupados en Suoem contra municipio por reducción de adicionales de policÃa
[descripcion_protagonista] => Trabajadores municipales
[descripcion_antagonista] => Municipio
[descripcion_demandaprinc] => suspension de contratacion de adicionales
[nivel_estado] => 3. Municipal
[fecha_comienzo] => 2013-01-03
[descripcion_sector] => Municipales
[fecha_final] =>
[marca_patronal] => 0
[SectorActividadCiuTa7] => Array
(
[id] => 12
[sector_actividad] => L. Administración publica y defensa planes de seguridad social de afiliación obligatoria
)
[SubsectorActividadTa8] => Array
(
[id] => 33
[id_sector] => 12
[descripcion] => L75. Otros
)
[Conflictos1HasActoresTa1] => Array
(
[0] => Array
(
[conflictos_1_id] => 133
[actores_ta1_id] => 10
)
)
[RelacionConflictualPrincipalTa9] => Array
(
[id] => 5
[descripcion] => A311. Trabajadores estatales // nivel municipal // capital // general
[privado_publico] => 1
[nivel_estado_o_sector] => A311
)
)
[FuentePrimariaTa3] =>
[FuenteSecundariaTa4] => Array
(
[id] => 1
[descripcion] => La Voz del Interior
)
[AlcanceTa5] => Array
(
[id] => 3
[descripcion] => Local/municipal
)
[LugaresTa6] => Array
(
[id] => 2
[depto_provincia] => Capital
)
[RespuestaEstadoTa13] => Array
(
[id] => 8
[descripcion] => Comunicación / niega
)
[ParticipacionBasesTa12] => Array
(
[id] => 5
[descripcion] => Sólo conducción
)
[NivelAgregadoTa15] => Array
(
[id] => 1
[nivel_agregacion] => Empresa o lugar de trabajo
[descripcion] =>
)
)
)
Luego, para poder listar los datos o pasarlos a un archivo CSV, en una vista de Symfony 1.4, procedo a utilizar la función setAttribute.
Luego, en la vista, será posible recorrer el array y volcar los datos en pantalla o en un archivo, sin necesidad de acceder al disco duro del servidor, ya que el array permanece en la memoria, generando un aumento notable de velocidad en las consultas complejas como esta.
Un artículo muy completo, donde se explica en detalle todos los tipos de Data Hydrators de Doctrine, con ejemplos, se puede consultar en: http://blog.micayael.com/2011/06/18/data-hydrators-con-symfony-1-4-y-doctrine/