Tomasz Wójtowicz

Tomasz Wójtowicz Programista Ruby on
Rails

Temat: Nadpisanie metody

Witam,

Mam dwie tabele "Dane personalne" i "Adres". Są one powiązane ze sobą relacją jeden do wielu (jedna osoba -> wiele adresów). W tabeli adres mam kolumne ktora informuje czy jest to adres główny czy nie. Chcąc wyświetlić wszystkie osoby wraz z jego glównym adresem robie takie zapytanie:


$this->personal_datas = Doctrine_Core::getTable('PersonalData')
->createQuery('p')
->leftJoin('p.Address a')
->where('p.status = 1')
->andWhere('a.main = 1')
->groupBy('p.id')
->execute();

Wyswietlają mi się te osoby ktore są aktywne (status = 1) z jego glównym adresem(a.main = 1). I wlasnie kwestia jest tego typu, że jezeli mam w bazie zaznaczonych kilka głównych adresów to wyswietla się ten co został wprowadzony jako pierwszy. To jest do jeszcze do przelkniecia bo ktos zobaczy ze zly adres sie wyswietla jako ten glówny to sobie zmieni. Ale jest drugi problem. Jezeli nie ebdzie zaznaczony zaden adres, to w ogole nie wyswietli się osoba bo wedlug warunku musi miec adres glówny. I teraz nie wiem czy starac sie w kodzie zabiezpieczyc tak zeby do takich sytuacji nie dochodzilo czy jest na to jakis fajny sposob :D.

Zastanawialem się zeby robic zapytanie


$this->personal_datas = Doctrine_Core::getTable('PersonalData')
->createQuery('p')
->where('p.status = 1')
->execute();


i potem przy wyswietlaniu w widoku robić tak

$personal_data->Address[0]->address
$personal_data->Address[0]->zip_code ....


W ten sposob doctrine tworzy drugie zapytanie pobierajac adres danej osoby. Tyle ze pobiera pierwszy wiersz z bazy a nie ten wlasciwy :P. W jaki sposob mozna nadpisac to zeby przy wywolaniu $personal_data->Address pobieralo adres z moimi ograniczenami (czyli main = 1).

Tylko czy jest sens tak robic bo jak np bede chcial wyswietlic 50 osob to powstanie 100 zapytan do bazy :P Wiec to chyba jednak odpada hehe :P

BTW: Tak w ogole to nie wiem czy nazwa tematu jest odpowiednia do tego problemu ale widze ze juz nie moge go zmienicTomasz Wójtowicz edytował(a) ten post dnia 13.12.10 o godzinie 20:51

konto usunięte

Temat: Nadpisanie metody

Tutaj Ci się przyda przy dodanie warunku z tabeli Address (a.main = 1 ) do joina.
Spójrz na keyworda WITH w doctrine http://www.doctrine-project.org/documentation/manual/1... .


$this->personal_datas = Doctrine_Core::getTable('PersonalData')
->createQuery('p')
->leftJoin('p.Address a WITH a.main = 1')
->where('p.status = 1')
->andWhere('a.main = 1')
->groupBy('p.id')
->execute();


A jezeli chcialbyś wyciągną w tym zapytaniu wszystkie główne adresy to chyba wystarczy wywalić tego groupBy ale głowy za to nie dam.
Pozdro
Tomasz Wójtowicz

Tomasz Wójtowicz Programista Ruby on
Rails

Temat: Nadpisanie metody

No i to jest to o co mi chodziło :) Dzięki wielkie :D Tam w tym zapytaniu co napisałes trzeba było jeszcze wywalić ->andWhere('a.main = 1') i jest wszystko fajnie :)

Jeszcze raz dzieki :)

Temat: Nadpisanie metody

Inny sposób (który osobiście bym preferował) to dodać do klasy PersonalData metodę:


public function getMainAdress()
{
foreach($this->Adress as $adress)
{
if($adress->main == 1)
{
return adress;
}
}

return false;
}


która będzie wyszukiwała i zwracała główny adres. Będziesz mógł ją wykorzystać w ten sposób:


$mainAdress = $personal_data->getMainAdress();
echo $mainAdress->address;
echo $mainAdress->zip_code;


(oczywiście warto by było zabezpieczyć kod na wypadek zwrotu false). Takie rozwiązanie ma jedną ważną zaletę ponad dqlem - zawsze gdy masz dostęp do obiektu PersonalData, będziesz mógł wydobyć jego główny adres, np:


$invoice->PersonalData->getMainAdress();


Jeżeli chodzi o wydajność takiego rozwiązania, to oczywiście będzie ono wolne, gdy nie wyciągniesz obiektów PersonalData wraz z obiektami Adress (wtedy będzie za każdym razem wykonywał zapytania do bazy). W przypadku, gdy obiekt wyciągłeś z adresami:


$this->personal_datas = Doctrine_Core::getTable('PersonalData')
->createQuery('p')
->leftJoin('p.Address')
->where('p.status = 1')
->execute();


zapytania nie będą wykonywane - jedyne spowolnienie (którego pewnie nawet nie zauważysz) to iteracja po kolekcji.

A ten groupBy to po co? W przypadku takiego dqla nie powinien mieć wpływu na wynik.

Aha - a co do wielu adresów oznaczonych jako główny(jeśli założenia nie przewidują takiej funkcjonalności), dobrze by to było zabezpieczyć , lub oprogramować - np w przypadku oznaczania adresu jako główny, reszta adresów jest automatycznie odznaczana. Bo na chwilę obecną, jeżeli nie określasz jawnie kolejności (orderBy) program będzie się dziwnie zachowywał (prawdopodobnie będzie zwracał wiersz ostatnio zmodyfikowany, zależy jak baza danych się zachowa).Michał Górny edytował(a) ten post dnia 14.12.10 o godzinie 18:54
Tomasz Wójtowicz

Tomasz Wójtowicz Programista Ruby on
Rails

Temat: Nadpisanie metody

Przetestuje tamten i ten sposób i zobacze, który wybiore :) Chociaż sposób Przemka jak narazie bardziej do mnie przemawia :) Bo robi dokładnie to o co mi chodziło lekko tylko zmieniając moje zapytanie. I wydaje mi sie że jest szybsze w wykonaniu (w sensie pracy bazy danych).
Michał Górny:
Aha - a co do wielu adresów oznaczonych jako główny(jeśli założenia nie przewidują takiej funkcjonalności), dobrze by to było zabezpieczyć , lub oprogramować - np w przypadku oznaczania adresu jako główny, reszta adresów jest automatycznie odznaczana. Bo na chwilę obecną, jeżeli nie określasz jawnie kolejności (orderBy) program będzie się dziwnie zachowywał (prawdopodobnie będzie zwracał wiersz ostatnio zmodyfikowany, zależy jak baza danych się zachowa).

Tak założenia sa takie że nie może być kilka głównych. Napisałem już metodę która w przypadku zaznaczenia głównego adresu odznacza reszte. Ale i tak wypadałoby zabezpieczyć wyswietlanie, gdyby czasem byly jednak dwa adresy oznaczony jako te główne.

Wyrzuciłem groupby bo faktycznie niepotrzebnie tutaj byl. W jego miejsce wstawiłem orderBy. Tylko sie zastanawiam wedlug ktorego pola sortowac. W przypadku gdyby jakims sposobem (dziura w programie :P lub ustawione przed kogos kto ma dostęp do panelu mysql) kilka adresów było jednak oznaczonych jako główne to nie wiem który adres wyswietlic :)
do wyboru mam ten najpozniej utworzony (orderBy 'created_at') lub ten co byl ostatnio modyfikowany (orderBy 'modified_at').
Tomasz Wójtowicz

Tomasz Wójtowicz Programista Ruby on
Rails

Temat: Nadpisanie metody

Dzisiaj potrzebowałem wykorzystać sposób Michała do innego problemu niż ten opisany wyzej i stwierdzam ze jednak sie mylilem i chyba nie do konca wtedy zrozumiałem twoje rozwiązanie. Sprawdzilem je i jednak tez jest dobre i chyba bede przerabial to co wtedy napisalem :P

Następna dyskusja:

Nadpisanie metody get*Table...




Wyślij zaproszenie do