2012-04-02 9 views
7

Tak, mam przedłużony CGridView włączyć funkcję wyszukiwania zaawansowanego dostosowane do potrzeb mojej organizacji.Yii - Manipulacja zapytań dla niestandardowej CGridView z wyszukiwania zaawansowanego

  • Filtr - pozwala pokazać/ukryć kolumny w tabeli, a także można zmienić kolejność kolumn, przeciągając ikonkę przeciągania po lewej stronie każdej pozycji.
  • Sortuj - Pozwala na wybór wielu kolumnach określ rosnącym lub malejącym.
  • Szukaj - Wybierz kolumnę i wstawić parametry wyszukiwania. Operatory dostosowane do typu danych wybranej kolumny.

Advanced Search Screenshot

Wersja 1 prace, choć powoli. Zasadniczo miałem ręce w wewnętrzne funkcjonowanie CGridView, gdzie wyrwać wyniki z DataProvider i zrobić wyszukiwania i sortowania w PHP przed renderowania zawartości tabeli.

Teraz piszę wersję 2, w której staram się skupić na sprytnym stworzeniu CDbCriteria, pozwalając MySQL wykonać ciężki lifting, aby działał szybciej. Implementacja jest trywialna, gdy mamy do czynienia z pojedynczą tabelą bazy danych. Trudność pojawia się, gdy mam do czynienia z 2 lub więcej tabel ... Na przykład, jeśli użytkownik chce wyszukać na polu, które jest STAT relacja, że ​​relacja muszę być obecny w moim zapytaniu abym zawierać porównań .

Oto jest pytanie. W jaki sposób mogę zapewnić, że Yii zawiera wszystkie relacje with w moim zapytaniu, aby uwzględnić porównania? podaję wszystkie moje relacje with moje kryteria w search funkcji modelu i próbowałem CDbCriteria za together ustawiona na true ...

public function search() { 
    $criteria=new CDbCriteria; 
    $criteria->compare('id', $this->id); 
    $criteria->compare(... 
    ... 
    $criteria->with = array('relation0','relation1','relation3'); 
    $criteria->together = true; 

    return new CActiveDataProvider(
     get_class($this), array(
      'criteria'=>$criteria, 
      'pagination' => array('pageSize' => 50) 
));} 

Wtedy będę wyrwać kryteria z DataProvider i add a few conditions dla przykładem, szukając dat> 1234567890. Ale nadal pojawiają się błędy jak ten ...

CDbCommand failed to execute the SQL statement: 
SQLSTATE[42S22]: Column not found: 1054 Unknown column 't.relation3' in 'where clause'. 
The SQL statement executed was: 
SELECT COUNT(DISTINCT `t`.`id`) FROM `table` `t` 
LEFT OUTER JOIN `relation_table` `relation0` ON (`t`.`id`=`relation0`.`id`) 
LEFT OUTER JOIN `relation_table` `relation1` ON (`t`.`id`=`relation1`.`id`) 
WHERE (`t`.`relation3` > 1234567890) 

Gdzie relation0 i relation1BELONGS_TO stosunki, ale każde STAT relacji, tutaj depicte d jako relation3, brakuje. Ponadto, dlaczego zapytanie to jest SELECT COUNT(DISTINCT 't'.'id')?

Edytuj @DCoder Oto konkretna relacja, z którą teraz pracuję. Główny stół to Call, który ma relację HAS_MANY do CallSegments, która utrzymuje czasy. Tak więc startTime połączenia jest minimalnym początkowym czasem wszystkich powiązanych przypisań połączeń. I startTime jest hipotetycznym relation3 w moim anonimowym błędzie zapytania.

'startTime' => array(self::STAT, 'CallSegments', 'call_id', 
      'select' => 'min(`start_time`)'), 

Edit Inne osoby Wysłano mnie do CDbCriteria's together property, ale jak widać powyżej, Obecnie próbuję że bezskutecznie.

Edit Wygląda emisji został mogły być zgłaszane: Yii i github bilety.

+1

Czy możesz pokazać bardziej powiązany kod, w szczególności deklaracje relacji modelu? Relacje STAT są zwykle wykonywane jako oddzielne zapytania. – DCoder

+0

W porządku @DCoder, dodałem relację, z którą teraz pracuję. Chcesz więcej? Jakikolwiek sposób dołączyć relację STAT w zapytaniu? Sądziłem, że po to jest CDBCriteria, ale najwyraźniej nie. –

+0

Nie jest dla mnie jasne, jaka jest twoja anonimowa relacja0, relacja1 i relacja3, ale myślę, że będziesz musiał wybrać call_id i min (start_time) w tabeli tymczasowej i dołączyć do tej tabeli zamiast polegać na STAT. Jeśli silnik bazy danych obsługuje kolumny obliczeniowe, może to być przyzwoita alternatywa. – DCoder

Odpowiedz

2

To nie jest dobry pomysł, aby pobrać sql z kryteriów i używać go samodzielnie.

Jeśli używasz „z” własności następnie można łatwo używać porównań jak:

$criteria->compare("`relation1`.`id`", $yourVarHere); 

także Yii nie zachowują się dobrze ze zgrupowania.

Moje podejście do stosunków STAT używa podzapytania w wybiera z Yii, a następnie poprzez:

$criteria->select = array("`t`.*", "(SELECT COUNT(*) FROM `relation3` WHERE `id` = `t`.id_relation3) AS `rel3`"); 
$criteria->having = "`rel3` > " . $yourValue; 

Powyższa metoda tworzy błąd w GridView paginacji ponieważ liczba odbywa się na innej kwerendy. Rozwiązaniem będzie upuść „z” własności i napisać dołącza przez siebie w nieruchomości jak „join”:

$criteria->join = "LEFT OUTER JOIN `relation_table` `relation0` ON (`t`.`id`=`relation0`.`id`) 
LEFT OUTER JOIN `relation_table` `relation1` ON (`t`.`id`=`relation1`.`id`) 
LEFT OUTER JOIN `relation_table` `relation3` ON (`t`.`id`=`relation3`.`id`)"; 
0

Jeśli błąd jest trochę trudno dostać pracę można użyć relacji stat jako prosty HAS_ONE z:

'select'=>'count(relation3.id)', 
'joinType'=>'left join', 
'group'=>'relation3.id', 
'on'=>'t.id = relation3.id', 
'together'=>true 

, aby uzyskać wartość zliczania obok wszystkich innych elementów?

Nie jestem pewien, jak dobrze by to działało w twoim przypadku, ale od czasu do czasu było dla mnie pomocne.

Powiązane problemy