Aquí es lo que hice para resolver esto sin ninguna consulta adicional:
Problema
necesario para añadir un campo COUNT personalizado a un conjunto de resultados típicos se utiliza con el Symfony Pager. Sin embargo, como sabemos, Propel no es compatible con esto. Así que la solución fácil es simplemente hacer algo como esto en la plantilla:
foreach ($pager->getResults() as $project):
echo $project->getName() . ' and ' . $project->getNumMembers()
endforeach;
Dónde getNumMembers()
ejecuta una consulta COUNT separado para cada objeto $project
. Por supuesto, sabemos que esto es extremadamente ineficiente porque puede hacer el COUNT sobre la marcha al agregarlo como una columna a la consulta SELECT original, guardando una consulta para cada resultado mostrado.
Tenía varias páginas diferentes que mostraban este conjunto de resultados, todas con diferentes criterios. ¡Así que escribir directamente mi propia cadena de consulta SQL con PDO sería demasiado complicado ya que tendría que entrar en el objeto Criteria y perder el tiempo tratando de formar una cadena de consulta basada en lo que haya en ella!
Por lo tanto, lo que hice al final evita todo eso, dejando que el código nativo de Propel trabaje con los criterios y cree el SQL como de costumbre.
1 - Primero cree los métodos [get/set] NumMembers() equivalentes de acceso/mutador en el objeto modelo que regresa con doSelect(). Recuerde, el programa de acceso ya no hace la consulta COUNT, simplemente mantiene su valor.
2 - Ir a la clase peer y anular los padres método doSelect() y copiar todo el código de la misma tal y como es
3 - Eliminar este poco porque getMixerPreSelectHook es un método privado de la base peer (o copiarlo en su equipo si lo necesita):
// symfony_behaviors behavior
foreach (sfMixer::getCallables(self::getMixerPreSelectHook(__FUNCTION__)) as $sf_hook)
{
call_user_func($sf_hook, 'BaseTsProjectPeer', $criteria, $con);
}
4 - Ahora agregue su campo personalizadas cuenta con el método doSelect en su clase peer:
// copied into ProjectPeer - overrides BaseProjectPeer::doSelectJoinUser()
public static function doSelectJoinUser(Criteria $criteria, ...)
{
// copied from parent method, along with everything else
ProjectPeer::addSelectColumns($criteria);
$startcol = (ProjectPeer::NUM_COLUMNS - ProjectPeer::NUM_LAZY_LOAD_COLUMNS);
UserPeer::addSelectColumns($criteria);
// now add our custom COUNT column after all other columns have been added
// so as to not screw up Propel's position matching system when hydrating
// the Project and User objects.
$criteria->addSelectColumn('COUNT(' . ProjectMemberPeer::ID . ')');
// now add the GROUP BY clause to count members by project
$criteria->addGroupByColumn(self::ID);
// more parent code
...
// until we get to this bit inside the hydrating loop:
$obj1 = new $cls();
$obj1->hydrate($row);
// AND...hydrate our custom COUNT property (the last column)
$obj1->setNumMembers($row[count($row) - 1]);
// more code copied from parent
...
return $results;
}
Eso es todo. Ahora tiene el campo COUNT adicional agregado a su objeto sin hacer una consulta por separado para obtenerlo a medida que escupe los resultados. El único inconveniente de esta solución es que ha tenido que copiar todo el código principal porque necesita agregar bits justo en el medio. Pero en mi situación, esto parecía un pequeño compromiso para guardar todas esas consultas y no escribir mi propia cadena de consulta SQL.
Gracias por esa respuesta, ¡me ha ayudado a resolver un problema diferente! –