Generalnie mógłbym to zrobić tak, napisać sobie model który wyciąga coś tam z bazy i w kontrolerze przekazywać co ma wyciągać i wyrzucać to do widoku. To jest proste, ale mi chodzi o to aby skorzystać ze standardowej funkcji search z jednego modelu i wykorzystać ja w innym kontrolerze nie tracąc funkcjonalności filtrowania danych.
np. mam dwa modele -> użytkownik i posty
i chciałbym aby teraz na liście użytkowników -> po kliknieciu w link wyświewtliła się lista jego postów z możliwością filtrowania, a nie jak standardowo -> szczegóły na temat użytkownika
Przecież kontroler nie jest w żaden sposób przypisany do modelu. Tworząc obiekt danego modelu w kontrolerze i przekazując go do widoku, możesz sobie wyświetlić co tam potrzebujesz. Tak samo to działa w drugą stronę - jeżeli jedna akcja ma aktualizować 2 modele to sprawdzasz sobie w kontrolerze zawartość $_POST, odpalasz walidacje na 2 modelach i jak jest ok to zapisujesz obydwa modele. To wersja prosta.
Wersja być może trochę trudniejsza, za to dużo "ładniejsza" pod względem jakości kodu i projektu systemu polega na uruchomieniu zapisu oraz usuwania danych w modelach zależnych wewnątrz zdarzeń modelu nadrzędnego. Są do tego rozszerzenia (zazwyczaj jednak strasznie przeładowane i nie zgrabne) na ten przykład: cadvancedarbehavior lub save-relations-ar-behavior. Zamiast korzystać z "zachowań" można or razu zaimplementować opcję zachowania spójności danych w modelu w funcjach: onBeforeSave oraz onBeforeDelete. Zazwyczaj sprowadza się to do uruchomienia walidacji, próby zapisu i ustawienia odpowiednio zmiennej składowej isValid klasy CModelEvent.
Podsumowując, nic nie stoi na przeszkodzie, żeby jedna akcja kontrolera obsługiwała kilka modeli. W widoku możesz sobie utworzyć 2 instancje CGridView po jednej do każdego modelu, i każda może obsługiwać inną funkcję search. Jeden, z nich może zostać ukryty i wyświetlać się tylko po jakimś zdarzeniu JS. Wolna wola . Możesz też na przykład stworzyć drugą akcję w kontrolerze która będzie odpalała partialRender i zaciągać dane do różnych modeli poprzez ajax.
Utwórz nową akcję kontrolera, w której filtrujesz posty po ID użytkownika wykorzystując relacje w rekordzie aktywnym
//w findByPk filtruj po czym chcesz
$user = new User;
$user->setAttributes($_POST);
User::model()->with('posts')->findByPk($user->id);
// i dalej standardowo jak w każdej akcji
Mam jeszcze pytanie odnośnie filtrowania danych(ten formularz do wyszukiwania). Czy wygenerowanie takiego grida możliwe jest tylko z danych pochodzących z CDbCriteria? I jeszcze jedno pytanie - przy schemacie użytkownicy -> tematy -> posty w dobrym tonie będzie trzymanie 3 modeli, obsługiwanych przez jeden kontroler, czy 1 model i 1 kontroler?
Nie wiem jak rozbudowany ma być system który piszesz, ale te modele które wymieniłeś mogą być bardzo duże, a i akcji może być sporo do obsługi każdego z nich. Moim zdaniem 3 kontrolery.
I teraz korzystając z Gii fajnie sobie generuje modele i działania CRUD - niestety wszystko żyje osobnym życiem
A z drugiej strony gdy stworze swój model i sam wyciągam odpowiednie dane z bazy poprzez stworzone zapytania to niestety w prawdzie dane trzymają się kupy, ale trace możliwości filtrowania danych(ta fajna wyszukiwarka z CGridView :/) i to jest katastrofa.
I nie bardzo wiem jak sobie z tym poradzić aby z jednej strony mieć możliwości modeli związanych z konkretnymi tabelami w bazie, a z drugiej zgrany system danych.
Pewnie to jakiś banał, ale w większości do tej pory korzystalem z proceduralnego stylu, teraz ciężko mi zrozumiec mechanizmy OOP
Pamiętaj, że zawsze możesz podać w gridzie w którym twoim modelem jest firma relację działy.
// w modelu Firma masz
public function relations()
{
return array(
'działy' => array(self::HAS_MANY, 'Dział', 'firma_id'), //działy
);
}
I wtedy w gridzie podajesz nazwę kolumny "name".
A teraz magia Yii
Jeżeli podejrzysz sobie to co zwracane jest w $_POST to zauważysz, że gdy będziesz filtrował po tym polu to w $_POST pojawi ci się oprócz $_POST[‘Firma’] również $_POST[‘Dział’]. Teraz wystarczy, że w akcji kontrolera przekażesz odpowiednio zawartość $_POST[‘Dział’] do: