CGridView - HAS_MANY + sortowanie..

Witam,

Przejrzałem już chyba całe tutejsze forum i nadal nie znalazłem rozwiązania mojego problemu…

Mam 2 tablice Article i Article_Txt w relacji Article HAS_MANY Article_Txt, kluczem obcym łączącym obie tablice jest artidx. W praktyce, z wykorzystaniem dodatkowego parametru language robi się z tego relacja 1:1 (1 artykuł ma 1 odpowiednik w tablicy tekstowej względem 1 języka). W wygenerowanym przez Gii CRUD dla Artykułu chciałem zrobić listę z wyszukiwarką (search), wzbogaconą o elementy z relacyjnej tablicy tj. pola z modelu Article + np. tytuł z Article_Txt (tylko w domyślnym języku - czyli praktycznie 1:1)…

Uświadomiłem sobie już, że nici z eager loading w CGridView przy takim układzie (HAS_MANY, MANY_MANY)… (czemu? nie rozumiem dlaczego można w $criteria metody search() używając with przekazać parametru, dzięki któremu join nie zwróci tablicy, a jedynie pojedyńczą encję przypisaną do głównego obiektu? czy jest to niedopatrzenie ze strony twórców fv?), więc wykorzystując lazy loading w kolumnie użyłem:


        array(

        	'name'=>'art_txts.name',

        	//'value'=>'$data->art_txts->name',

        	'value'=>'ArticleTxt::model()->findByAttributes(array("artidx"=>$data->artidx, "language"=>0))->name'

        ),

i powiedzmy, że ok - wyświetla się aczkolwiek wykonuje się więcej sqli niż bym chciał…

Za nic nie mogę dojść do tego jak nad polem z tytułem wyświetlić filter w postaci pola tekstowego. Nie chcę wyświetlać selecta, gdyż jest to tytuł artykułu, więc wybór z tablicy opcji mija się z celem…

Relacja:


'art_txts' => array(self::HAS_MANY, 'ArticleTxt', 'artidx',

Kombinacje w search(): …


		$criteria=new CDbCriteria;


		$criteria->compare('artidx',$this->artidx);

		$criteria->compare('catidx',$this->catidx);

		$criteria->compare('status',$this->status);

		$criteria->compare('updated_at',$this->updated_at,true);

		$criteria->compare('created_at',$this->created_at,true);

		$criteria->compare('views_cnt',$this->views_cnt);

		

		//$criteria->compare('art_txts.name', $this->art_txts->name, true);

		

		$criteria->with = array(

			'art_txts'=>array(

				'select'=>'name', 

				//'joinType' => 'INNER JOIN',

				'condition' => 'art_txts.language=:language AND art_txts.artidx = :artidx', 

				'params' => array(':language' => 0, ':artidx' => $this->artidx),

				'together' => true

			),

		);

		

		

		return new CActiveDataProvider(get_class($this), array(

			'criteria'=>$criteria

			)

		));

Proszę o jakieś naprowadzenie. Może ja coś robię źle?

Podsumowując, 2 pytania:

Czy istnieje w przypadku takim jak zaprezentowałem jakiś sposób użycia eager loading do wyświetlenia danych w CGridView ?

W jaki sposób nie mając pola art_txts.name zdefiniowanego w modelu Article mogę utworzyć filter tekstowy w wyszukiwarce?

Z góry dzięki za odp.

Wydaje mi się, że główną przyczyną twojego problemu jest to, że masz zdefiniowaną relację art_txts jako HAS_MANY i właśnie tę relację chcesz użyć do otrzymania jednego tekstu. HAS_MANY zawsze zwracać będzie tablicę, nawet jeśli będziesz miał w niej jeden element (np. konkretny tekst dla konkretnego języka).

Powinieneś utworzyć sobie nową relację, np. articleTextWithLang, zdefiniowaną jako HAS_ONE i używać ja za każdym razem podając


'condition' => 'art_txts.language=:language'

Super, dzięki :) Działa oczywiście, tylko pytanie czy nie gryzie się to w żaden sposób z dobrą praktyką programowania w Yii (tj. 2 relacje do tej samej tablicy w różnych wariantach)?

Jakbyś mi jeszcze pomógł zdefiniować tekstowy filter dla tego pola z relacji… byłbym bardzo wdzięczny ;)

Poradziłem sobie :)

Jakby jeszcze komuś było potrzebne:

Model:


public $name; //dodane pole

... 

		$criteria->with = array('art_txts_with_lang');

		$criteria->together = true;

		$criteria->compare('art_txts_with_lang.name', $this->name, true);

				

		return new CActiveDataProvider(get_class($this), array(

			'criteria'=>$criteria,

			'sort'=>array(

				'attributes'=>array(

					'*',

					'name'=>array(

						'asc'=>'art_txts_with_lang.name',

						'desc'=>'art_txts_with_lang.name DESC',

						'label'=>'Tytuł'

					)

				)

			)			

		));



Widok (kolumna CGridView):




        array(

        	'name'=>'name',

        	'value'=>'$data->art_txts_with_lang->name',

        ),