Grzegorz P.

Grzegorz P. CodeTwo sp. z o.o.
sp. k.

Temat: Relacja 1:1 i lista

Witam!

Mój problem przestawia się następująco:

Tabele:
Passenger {id, name, surname}
BlackList {id, content, passenger_id}

Passenger:BlackList 1:0
O spójnośc troszczę się na poziomie aplikacji i bazy danych (Uniq na passanger_id)

Pytania dwa:

1. Jak w sposób najbardziej ekonomiczny uzyskać listę pasażerów z informacją czy jest on czy go nie ma na czarnej liście?

2. W jaki sposób uzyskać taka informację już dla konkretnego pasażera. Podejrzewam, że WHERE ID=x z rozwiązania pkt. 1. Ale jak?

Pomóżcie!

GP.

PS: W temacie popełnił się błąd. Miało być 1:0.Grzegorz P. edytował(a) ten post dnia 02.10.08 o godzinie 23:40

konto usunięte

Temat: Relacja 1:1 i lista

trzeba złączyć te dwie tabele razem:)
jeżeli używasz Propel to jest tam metoda addJoin.
popatrz jakie parametry ona przyjmuje i odpowiednio to wykorzystaj.
Grzegorz P.

Grzegorz P. CodeTwo sp. z o.o.
sp. k.

Temat: Relacja 1:1 i lista

Złączając te dwie tabele otrzymam listę tylko i wyłącznie pasażerów znajdujących się na czarnej liście.

konto usunięte

Temat: Relacja 1:1 i lista

hmm nawet jak łączysz LETF JOINem ?
no właśnie. łącz LEFT JOINem :)
jeżeli pasażer nie jest na czarnej liście dostaniesz w kolumnie wartość NULL.
Grzegorz P.

Grzegorz P. CodeTwo sp. z o.o.
sp. k.

Temat: Relacja 1:1 i lista

Adam W.:
hmm nawet jak łączysz LETF JOINem ?
no właśnie. łącz LEFT JOINem :)
jeżeli pasażer nie jest na czarnej liście dostaniesz w kolumnie wartość NULL.

I już prawie w domu jesteśmy. Bo na SQL klepanym faktycznie zadziałało.

Teraz tylko dodać LEFT JOIN do obiektu Criteria() - pomożesz?

Bo chce dodatkowo paginować sobie listę, więc nie mogę użyć PassangerPeer
Grzegorz P.

Grzegorz P. CodeTwo sp. z o.o.
sp. k.

Temat: Relacja 1:1 i lista

Znalazłem to czego szukałem:
$c->addJoin(PassengerPeer::ID, BlacklistPeer::PASSENGER_ID, Criteria::LEFT_JOIN);

Pytanie tylko jak w widoku sprawdzić czy pasażer jest na liście.
Instrukcja:
$passenger->getBlacklists() niestety wykonuje zapytanie do bazy danych. Dokładnie pyta o czarne listy pasażera. W tym momencie w/w złączenie jest niepotrzebne. Tak przynajmniej wskazuje debugBar.

Jest jakiś sposób na minimalizację liczby zapytań?

konto usunięte

Temat: Relacja 1:1 i lista

z tym Propelem to tak właśnie dziwnie jest.
najlepiej jakbyś w obiekcie Pager ustawil metode pobierania na coś z JoinAll
wtedy ci odpowiednio połączy tabele i pobierze wyniki.
tylko musisz mieć odpowiednio zrobione modele - czyli odpowiednio rozpisany schemat bazy.
Grzegorz P.

Grzegorz P. CodeTwo sp. z o.o.
sp. k.

Temat: Relacja 1:1 i lista

Adam W.:
z tym Propelem to tak właśnie dziwnie jest.
najlepiej jakbyś w obiekcie Pager ustawil metode pobierania na coś z JoinAll
wtedy ci odpowiednio połączy tabele i pobierze wyniki.
tylko musisz mieć odpowiednio zrobione modele - czyli odpowiednio rozpisany schemat bazy.

Faktycznie bardzo dziwne.

Ale może ktoś podsunie jakieś ciekawe rozwiązanie, bo nie wieże, że przy listowaniu 100000 obiektów muszę wykonać dodatkowe 100000 zapytań.Grzegorz P. edytował(a) ten post dnia 03.10.08 o godzinie 00:58

konto usunięte

Temat: Relacja 1:1 i lista

ale to nic trudnego. nie ma żadnych ciekawych rozwiązań.
nie ma co tu kombinować z pluginem (jest taki do specjalnego łączenia tabel). wystarczy odpowiednia struktura:

passenger:
attributes: {phpName: Passenger}
id: {type: integer, required: true, primaryKey: true, autoIncrement: true}
name: {type: varchar(32)}
surname: {type: varchar(32)}
blacklist:
_attributes: {phpName: Blacklist}
id: {type: integer, required: true, primaryKey: true, autoIncrement: true}
content: {type: varchar(32)}
passenger_id: {type: integer, foreignTable: passenger, foreignReference: id, required: true, onDelete: cascade}


a później

$c = new Criteria();
$c->addJoin(PassengerPeer::ID, BlacklistPeer::passenger_id, Criteria::LEFT_JOIN);
$pager = new sfPropelPager('passenger', 9);
$pager->setCriteria($c); $pager->setPeerMethod('doSelectJoinAll');
$pager->setPage($this->getRequestParameter('page', 1));
$pager->init();


doSelectJoinAll powinno spowodować, że w widoku po czymś takim
$passenger->getBlackList()->getContent()

nie powinny wykonywać się dodatkowe zapytania.
Grzegorz P.

Grzegorz P. CodeTwo sp. z o.o.
sp. k.

Temat: Relacja 1:1 i lista

Jest tak:


passenger:
id: { lazyLoad: false, type: INTEGER, primaryKey: true, required: true, autoIncrement: true }
name: { primaryKey: false, autoIncrement: false, lazyLoad: false, type: VARCHAR, size: '255', required: true }


blacklist:
_attributes: { skipSql: false, abstract: false }
id: { lazyLoad: false, type: INTEGER, primaryKey: true, required: true, autoIncrement: true }
passenger_id: { primaryKey: false, autoIncrement: false, index: unique, lazyLoad: false, type: INTEGER, required: true, foreignTable: passenger, foreignReference: id, onDelete: cascade, onUpdate: none }
content: { primaryKey: false, required: false, autoIncrement: false, lazyLoad: false, type: LONGVARCHAR }


poźniej
[code]
$c = new Criteria();
$this->orderby = $request->getParameter('orderby','n');
$c->addJoin(PassengerPeer::ID, BlacklistPeer::PASSENGER_ID, Criteria::LEFT_JOIN);

$pager = new sfPropelPager('Passenger', 3);
$pager->setCriteria($c);
$pager->setPeerMethod('doSelectJoinAll');
$pager->setPage($request->getParameter('page', 1));
$pager->init();
$this->pager = $pager;

$this->passengers = PassengerPeer::doSelect($c);
[code]

w widoku
[code]
$passenger->getBlackList()->getContent()
[/code]

W efekcie
[quote]
Fatal error: Call to a member function getContent() on a non-object in [...] indexSuccess.php
[/quote]

Żeby było śmieszniej,
[code]
$passenger->getBlackList()
[/code]

wykonuje dodatkowe zapytania.

No koszmar normalnie.

konto usunięte

Temat: Relacja 1:1 i lista

$this->passengers = PassengerPeer::doSelect($c);

tego już nie musisz robić, to za Ciebie robi Pager. popatrze na metody pagera bo jest tam metoda która zwraca wyniki. a jak już tak chcesz to zrób tak jak Ci pisałem, czyli użyj metody doSelectJoinAll.
i popatrz w katalogu lib/model na pliki związane z tymi tabelami - tam masz wszystkie metody, z których możesz korzystać. Możliwe jest, że coś jest nie tak z nazwami, czyli nie getBlackList tylko getBlacklist (tylko taki przykład).
Grzegorz P.

Grzegorz P. CodeTwo sp. z o.o.
sp. k.

Temat: Relacja 1:1 i lista

Zrobiłem tak jak mówisz, czyli


$c = new Criteria();
$c->addJoin(PassengerPeer::ID, BlacklistPeer::PASSENGER_ID, Criteria::LEFT_JOIN);

$pager = new sfPropelPager('passenger', 3);
$pager->setCriteria($c);
$pager->setPeerMethod('doSelectJoinAll');
$pager->setPage($request->getParameter('page', 1));
$pager->init();
$this->pager = $pager;
$this->passengers = $pager->getResults();


I niestety, w widoku

$pager->getResults();

każdorazowo wykonuje zapytanie. Poprawne, pozwalające wyciągnąć dane, które mnie interesują. Ale zawsze jest to kilka razy wytonowane. Dlatego listę pasażerów do widoku przesyłam w tablicy obiektów $passenger.

I dalej chcąc dostać się do informacji, czy dana osoba jest na czarnej liście wykonuje się ten nieszczęsny SELECT i głęboko w poważaniu cały system ma to, że chwile wcześniej wykonał LEFT JOIN.

Wnioskuję, że nie da się uzyskać obiektu wypełnionego, tak jak bym chciał? Wydaje mi się to niemożliwe... bo z wydajnością trzeba się liczyć.

konto usunięte

Temat: Relacja 1:1 i lista

oczywiście jest to możliwe. tylko wymaga pewnego zacięcia i drążenia tematu:)
trzeba zobaczyć w plikach modeli czy tam jest wszystko w porządku.
Grzegorz P.

Grzegorz P. CodeTwo sp. z o.o.
sp. k.

Temat: Relacja 1:1 i lista

A może to o lazyload chodzi?
Mam na false, jak widać wcześniej w schema.yml.

Na razie odpuszczam ten problem. Może ktoś wcześniej go rozwiązał.

Choć będzie mnie wkurzało, że generując prostą listę wykonuję n+2 zapytań, gdzie n jest długością listy. Wrrr....Grzegorz P. edytował(a) ten post dnia 03.10.08 o godzinie 13:32

Następna dyskusja:

Doctrine, relacja M:N - dod...




Wyślij zaproszenie do