Symfony admin generator – optymalizacja zapytań do bazy dla Doctrine

Ostatnio w projekcie Symfony 1.1 z użyciem Doctrine, dzięki webdebug toolbarowi, dostrzegłem czegoś, co mnie przeraziło. Otóż, jeśli w wygenerowanym przez Symfony adminie mamy klucze obce na liście, to wywoła on tyle zapytań ile elementów * ilość kluczy obcych.

Załóżmy, że mamy następujący schemat:

Kategoria:
  columns:
    nazwa: string(255)

Produkt:
  columns:
    nazwa: string(255)
    kategoria_id: integer
  relations:
    kategoria:
      class: Kategoria

Natomiast w generator.yml mamy zdefiniowane:

generator:
  class:              sfDoctrineAdminGenerator
  param:
    model_class:      Produkt
    theme:            default
    list:
      display:        [nazwa,kategoria]

To w przypadku kategoria, generator będzie wywoływał zapytanie w stylu

select * from kategoria where id = ?

co przy domyślnych 20 rekordach na stronę i przykładowo 3 kluczach obcych wygeneruje ponad 60 zapytań. Tego prawdopodobnie nie chcemy.

Rozwiązaniem w tej sytuacji jest zastosowanie parametru peer_method (znanego mi jeszcze z czasów używania Propela), znajdujące się w sekcji list.

Występuje tu jednak kilka założeń, o których warto wiedzieć. Po pierwsze: metoda którą określamy w peer_method musi znajdować się w klasie wskazanej w model_class (w naszym przypadku Produkt) i nie może być to metoda statyczna. Po drugie: metoda ta musi zwracać instancję klasy Doctrine_Query. Po trzecie, metoda ta musi mieć zakończenie nazwy pod postacią TableProxy. Po czwarte (tu tkwi największy trick): w złączeniach DQL nie możemy używać własnych aliasów, tylko aliasować pełnymi nazwami klas.

Oto przykład:

plik /lib/model/doctrine/Produkt.class.php

class Produkt extends BaseProdukt
{
  public function polaczZKategoriamiTableProxy()
  {
    return Doctrine_Query::create()->from('Produkt')->innerJoin('Produkt.kategoria'); //->from('Produkt p')->innerJoin('p.kategoria') jest błędne!
  }
}

plik /apps/backend/modules/produkty/config/generator.yml

generator:
  class:              sfDoctrineAdminGenerator
  param:
    model_class:      Produkt
    theme:            default
    list:
      peer_method:    polaczZKategoriami
      display:        [nazwa,kategoria]

Dzięki temu w znaczynym stopniu ograniczymy zapytania do bazy :-)

edit: już wkrótce to rozwiązanie tego samego problemu dla Symfony 1.2 (tam niestety zrezygnowano z peer_method).


Tagi: , , ,

Podobne wpisy

6 Responses to “Symfony admin generator – optymalizacja zapytań do bazy dla Doctrine”

  1. Przemysław Piechota Says:
    Kwiecień 8th, 2009 at 17:15

    W symfony 1.2 nie zrezygnowano całkowicie z peer_method.
    Można ją ustawić w klasie NazwaModułuGeneratorConfiguration.class.php która znajduje się w katalogu NazwaModułu/lib/ .
    W tej klasie można nadpisać funkcję getPeerMethod() .

  2. eXtreme Says:
    Maj 22nd, 2009 at 08:15

    Ej sorry ale co ty za głupoty wygadujesz tutaj: “: w złączeniach DQL nie możemy używać własnych aliasów, tylko aliasować pełnymi nazwami klas.”
    :O Toż to herezja! Od kiedy niby “nie możemy”? Zawsze można było i się da!

  3. wowo Says:
    Maj 22nd, 2009 at 08:26

    eXtreme: nie można w przypadku generatora, bo on już sam ustawia alias na starcie…

  4. eXtreme Says:
    Maj 22nd, 2009 at 13:59

    Można. :)

    Po pierwsze, to chyba zamiast “peer_method”, powinno być “table_method”.
    Druga sprawa, to $q->getRootAlias() które pozwala zwrócić domyślnie ustawiony alias dla bazowego modelu.

    Przykładowy kod jakiego ja używam: (nie wiem czy masz tu możliwość włączenia jakiegoś formatowania, więc wklejam na wklejke :P)

    http://wklej.org/hash/14cd5ef3cf/

    BTW. Popraw linki pod autorem komentarza bo doklejasz tam atrybut “rel” ale chyba niezbyt prawidłowo. ;)

  5. janek Says:
    Czerwiec 26th, 2009 at 09:56

    w generate.yml można ustawić table_method
    tam podając, która metoda ma zostać wywołana do pobierania danych.
    a jeżeli chodzi o aliasy w zapytaniu to można tak:
    $rootAlias = $q->getRootAlias();
    $q->leftJoin($rootAlias . ‘.Powiat p’);
    return $q;

  6. zajefajnyx Says:
    Listopad 23rd, 2009 at 22:07

    Chcemy wiecej :D

Skomentuj