Jeden widok, kilka modeli

Witam, dopiero zaczynam prace z Yii i napotkałem taki problem:

Tworze sobie 3 tabele w bazie z kluczami obcymi tworzącymi relacje między tymi tabelami. Za pomocą Gii generuje modele i crud.

Wszystko ładnie pięknie tylko, że wszystko żyje osobnym życiem, ja chciałbym to jakos połaczyć, a więc

wchodze pod adres

domena.pl/cA

-> lista danych z możliwością edycji z tabeli A

klikam w jakąś kolumnę z A i przenosi mnie to do listy danych z B(z możliwością edycji), a gdy klikam w B to dostaje listę C(z możliwościa edycji).

Rozsądnie byłoby mieć to pod jednym adresem np.

domena.pl/cA

domena.pl/cA/B

domena.pl/cA/B/C

Nie bardzo wiem jak się za to zabrać i stoję w martwym punkcie.

Jakas podpowiedź, sugestie, link do dobrego tutka?

Dzięki bardzo.

No to przekazuj sobie do kontrolera parametr i wg niego filtruj dane z bazy.

kontroler

hm… nie do końca o to chodzi.

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



Dzięki wielkie. Udało mi się opanować ten temat.

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.

Hm…?

Może ostatni przykład nie był za dobry.

Schemat:

  • Firma

– Działy

— Pracownicy

  • Firma

– Działy

— Pracownicy

I teraz korzystając z Gii fajnie sobie generuje modele i działania CRUD - niestety wszystko żyje osobnym życiem :confused:

A z drugiej strony gdy stworze swój model i sam wyciągam odpowiednie dane z bazy poprzez stworzone zapytania to niestety :confused: 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 :confused:

Także każda wskazówka mile widziana.

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:

a) metody search

B) metody with jeżeli używasz relacji;