Oto co zrobiłem, aby rozwiązać ten problem bez żadnych dodatkowych zapytań:
Problem
potrzebne, aby dodać niestandardowe pole liczyć do typowego zestawu wyników używanego z Symfony pager. Jednak, jak wiemy, Propel nie obsługuje tego po wyjęciu z pudełka. Tak więc proste rozwiązanie jest po prostu zrobić coś takiego w szablonie:
foreach ($pager->getResults() as $project):
echo $project->getName() . ' and ' . $project->getNumMembers()
endforeach;
Gdzie getNumMembers()
prowadzi oddzielne kwerendy liczyć dla każdego obiektu $project
. Oczywiście wiemy, że jest to bardzo nieefektywne, ponieważ możesz wykonać COUNT w locie, dodając go jako kolumnę do oryginalnego zapytania SELECT, zapisując zapytanie dla każdego wyświetlanego wyniku.
Miałem kilka różnych stron wyświetlających ten zestaw wyników, wszystkie używające różnych kryteriów. Napisanie własnego ciągu zapytań SQL z PDO byłoby więc zbyt kłopotliwe, ponieważ musiałbym dostać się do obiektu Criteria i rozejrzeć się, próbując utworzyć ciąg zapytania na podstawie tego, co w nim było!
To, co zrobiłem na koniec, unika tego wszystkiego, pozwalając, aby natywny kod Propla działał z kryteriami i jak zwykle tworzył SQL.
1 - najpierw utworzyć [get/ustawienie] NumMembers() równoważne metody dostępowej/modyfikujące w modelu obiektu zostanie zwrotu przez doSelect(). Pamiętaj, że akcesor nie wykonuje już zapytania COUNT, a jedynie przechowuje jego wartość.
2 - Idź do klasy rówieśniczej i zastąpić rodzica doSelect() metoda i skopiować cały kod z nią dokładnie, jak to jest
3 - Usuń ten bit bo getMixerPreSelectHook to prywatna metoda peer bazowej (lub skopiuj go do swojej peer, jeśli jest to potrzebne):
// symfony_behaviors behavior
foreach (sfMixer::getCallables(self::getMixerPreSelectHook(__FUNCTION__)) as $sf_hook)
{
call_user_func($sf_hook, 'BaseTsProjectPeer', $criteria, $con);
}
4 - teraz dodać niestandardowe pole liczyć do sposobu doSelect w swojej klasie rówieśniczej:
// 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;
}
to wszystko. Teraz masz dodane dodatkowe pole COUNT do twojego obiektu, nie robiąc oddzielnego zapytania, aby uzyskać je, gdy wyplujesz wyniki. Jedyną wadą tego rozwiązania jest to, że musisz skopiować cały kod nadrzędny, ponieważ musisz dodać bity dokładnie w jego środku. Ale w mojej sytuacji wydawało mi się to małym kompromisem, aby zapisać wszystkie te zapytania i nie pisać własnego ciągu zapytania SQL.
Dzięki za odpowiedź - pomogło mi to rozwiązać inny problem! –