Autor Zpráva
Someone
Profil
Dobrý večer, rád bych se zeptal, jak by měl vypadat správný návrh poměrně jendoduché MVC struktury u kategorií a článků.

A1) .cz/kategorie/ostatni/
A2) .cz/ostatni/jak-jsem-neuvaril-polevku/ případně .cz/article/jak-jsem-ji-nakonec-uvaril/

Má otázka je poměrně jednoduchá, jak správně navrhnout strukturu takového zobrazení?

Napadá mě několik možností:
B1) mít pro kategorii i článek zvlášť controller (category_controller & article_controller) (toto se mi nelíbí, protože tam není žádné propojení kategorie s článkem)
B2) mít to strukturovaně, otázkou je u jakého rodiče začít:
ad B2) categories -> category -> ?articles? (viz bod 3) -> article
Má to vůbec cenu začínat tak vysoko jako jsou všechny kategorie? Mně osobně se to zdá jako to "pravé objektové", ale je to pouze můj názor a taky to bude dost individuální.

Zase na druhou stranu když bychom měli adresu .cz/article/clanek/, tak není jasné z jaké kategorie článek je, tudíž se nedá zavolat controller kategorie s tím, že se pak zavolá metoda showArticle: $kategorie_controller -> showArticle($jmeno_clanku);, ale je třeba volat rovnou třídu buďto: $articles->showArticle($jmeno_clanku) (viz. bod 3 zda (ne)použít "articles") a nebo přímo $controller = new Article($jmeno_clanku) a předat jméno přes konstruktor.

B3) Uvažoval jsem i nad "articles" jakožto nad třídou, která by byla nadřazené třídě article, ale podřazená třídě category. Zde jsem ještě nedospěl k nějakému závěru, protože si nejsem jistý, jestli by se měla už samotná kategorie brát jako seskupení všech článků. (více se mi líbí nepoužití "articles")

Na závěr bych to asi nějak shrnul a vás bych požádal o nějaké rady/tipy/triky/nápady.

categories -> category -> ?articles? -> article // stále nevím jak s těmi articles

C1) .cz/categories/ ->
$controller = new Categories();


C2) .cz/category/ostatni/ ->
$controller = new Categories(); $controller->showCategory('ostatni');
nebo jen
$controller = new Category('ostatni');


C3) .cz/article/clanek/ ->
$controller = new Articles(); $controller->showArticle('clanek')
nebo jen
$controller = new Article('clanek');
// tady asi záleží i na struktuře adres

C4) .cz/ostatni/muj-clanek/ ->
$controller = new Categories(); $category = $controller->getCategory('ostatni'); $category->showArticle('muj-clanek');
// když by ta struktura byla takováto tak by "articles" byly ze hry asi stoprocentně.

Předem děkuji za váš čas a za jakékoliv rady a nápady.
Tori
Profil
Someone:
A ptáte se teda na návrh používaných URL, anebo na návrh rozdělení kontrolerů/metod? Jestli tomu správně rozumím, tak to jsou dvě různé věci, které spolu nemusí mít nic společného (jejich propojení obstará router a ten můžete nastavit jakkoliv).

Co všechno ovlivní to, v jaké kategorii je článek? Asi bych to rozdělovala podle toho.
Např.
- URL /recenze/nějaký-název-článku by mi zpracovávala metoda ClankyController->recenze($url), protože tam chci odlišné zobrazení (= jiná metoda view), nebo se z DB tahají ještě jiná data, než u ostatních článků
- ostatní články používají stejné šablony, potřebují stejná data z DB, takže URL /články/název-článku i /návody/třípokojová-psí-bouda by měla na starosti ClankyController->clanky($url)
Someone
Profil
Tori:
Ptám se na objektový návrh. Vaše "ClankyController" se zdá být podobné mému "Articles". Má otázka je stále stejná. Je jasné že když budu chtít vypsat všechny kategorie, tak controller bude např. objekt categories tj.: $controller = new Categories(); $controller->showAll(); Mně jde o to, jak udělat to volání, když budu volat konkrétní kategorii nebo článek. Mám to volat tak jako to jde hierarchicky? (.cz/ostatni/clanek/) $controller = new Categories(); $category = $controller->getCategory('ostatni'); $category->showArticle('clanek') nebo vytvář jen objekt articles, který se bude starat o články? Řekněme, že máme tyto dvě adresy

1) .cz/ostatni/clanek/
2) .cz/category/ostatni/

Jak je to víc "správné"?

ad 1 a)
$controller = new Categories();
$category = $controller->getCategory('ostatni'); // vrátí objekt category
$category->showArticle('clanek');

ad 1 b)
$controller = new Categories();
$category = $controller->getCategory('ostatni');
$articles = $category->getAllArticles(); // zde by category nezastupovala funkčnost "articles" resp. "ClankyController";
$articles->showArticle('clanek');

ad 1 c) // vzít pouze název článku a předat ho konstruktorem objektu Article (toto se mi moc nezamlouvá)
$controller = new Article('clanek');
$controller->showAsArticle(); // metodou by se asi určilo o jaký typ šablony se bude jednat.

// už to nebudu rozepisovat, ale ještě mě napadá mít pouze objekt Category, u kterého by se volala buďto: metoda getAllArticles (podobné u 1b) nebo by se rovnou volal článek ->showArticle('clanek');

ad 2) Tady je to v podstatě to samé až na to, že je to posunuté o řád víš. Mít či nemít kontajner všech kategorií nebo volat rovnou objekt pro samotnou kategorii, něco jako new Category('ostatni');
Tori
Profil
Co dělá třída Categories? Je to model v MV* aplikaci, nebo má jinou funkci, nebo nepoužíváte MV* vzor, ...?
Someone
Profil
Tori:
Třída categories má fungovat podovně jako "ClankyController" s tím rozdílem, že spravuje všechny kategorie. Obsahovala by něco jako metody getAllCategories(), showCategory() atd.. Ostatně její použití je znázorněno v 1a) 1b). Má otázka zní, zda vůbec začínat takto vysoko jako je objekt categories, popř. jakou z mnou uvedených (případně jiných) metod(způsobů) použít.
Tori
Profil
Jaký na to máte názor ostatní, zkušenější?
Mám pocit, že jsem tohle vlákno trochu zasekla, aniž by se došlo k nějakému závěru/řešení (které by mě samotnou taky zajímalo).
Mikrouš
Profil
Podle mě by měl být trvalý odkaz jedinečný pro daný objekt v rámci celého webu. Čili .cz/clanek/nejaky-unikatni-nazev-clanku a .cz/kategorie/nejaky-unikatni-nazev-kategorie. Pokud toto pravidlo zavedete, půl problémů zmizí (i tak se to i používá - čím delší COOL adresa, tím je COOL méně).
Someone
Profil
Mikrouš:
Nevím co si představit pod spojením "jedinečný pro daný objekt". Jinak to stále neodpovídá na položenou otázku.
Mikrouš
Profil
Objekt jsem nemyslel programově (objekt = clanek, kategorie...). Permalink článku bude jedinečný v rámci permalinků článku, permalink kategorie bude jedinečný v rámci kategorií. A vyhnul byste se konstrukci ".cz/ostatni/muj-clanek/". Uvažuju totiž ještě různá zanoření.

Z jaké kategorie článek je, by se nezjišťovalo přes Clanek->getCategory(); Odporuje to vztahu má. (Článek nemá kategorii ani není kategorie.) Použil bych konstrukci Kategorie::vratInstanci(Clanek); (názvy funkcí možná volím nevhodné, ale jde o princip) případně Kategorie::vratInstanciRodice(Kategorie), pokud by bylo povolené zanořování (nejvyšší úroveň by vrátila null; zjisteni rodice by ale probehlo az v momente jeho pozadavku na zjisteni).

Výpis článků v Kategorie řeším přes kolekci (ale dá se použít i obyčejné pole), která je zároveň členskou proměnnou ve třídě Kategorie (protože kategorie MÁ články - ale zároveň může mít i cokoliv jiného - např. další podkategorie). A volá se v metodě (při prvním volání; pokud totiž vůbec výpis čehokoli nechci tak se nemusí přistupovat do DB) Kategorie->getClanek(permalink): např.

Kolekce->nacti($Kategorie);
// cyklus
Kolekce->vrat(index);
// vyhledani rovnosti permalinku
// konec cyklu
Jan Tvrdík
Profil
Someone:
To, co tady vymýšlíš, nemá s MVC architekturou moc společného.

Uvažoval jsem i nad "articles" jakožto nad třídou, která by byla nadřazené třídě article, ale podřazená třídě category.
Naprostý nesmysl porušující základy OOP. Připadá ti třída Articles jako speciální případ třídy Category?

V podstatě všechny varianty, která tady uvádíš jsou z pohledu MVC špatně. Máš v tom takový zmatek, že není vůbec jasné, co by dle tebe mělo patřit do modelu a co do controlleru.
Co se týče jedná z úvodních otázek, tak článek a kategorie rozhodně potřebují dva samostatné controllery, žádná dědičnost nepřipadá v úvahu.

Na controlleru nemají co dělat metody jako getCategory() vracející instanci nějaké entity. Na controlleru má být spíš něco jako render(). Stejně tak na třídách patřící do modelu nemůžou být žádné metody starající se o vykreslování (jako např. showArticle).
Someone
Profil
Jan Tvrdík:
Děkuji za reakci, ale poprosil bych o trochu konstruktivnější kritiku. Všude jsi uvedl co je špatně. Trochu mi to připomíná odpověď "máš to rozbité". Už z první věty mi je jasné, že něco dělám špatně, ale dozvídám se to i v těch následujících. Ocenil bych, když bys uvedl nějaký nástin správného řešení. Dříve jsem měl controllery rozdělené podle stránky. přidání,odstranění, kategorie, článek atd... Ale přijde mi, že by tomu tak být nemělo. Viděl bych to spíš na nějakou třídu, která by obstarávala vytvoření článku, jeho úpravu, odstranění publikování atd., ale nejsem si jistý, proto jsem zakládal toto téma.

žádná dědičnost nepřipadá v úvahu
A proč to? Věřím tomu, že to má nějaký důvod, ale bez nějakého vysvětlení, opodstatnění je to prostě tvrzení, které mě nějak nepriblíží k odpovědi na mou otázku.

Jinak bych poprosil o ztlumení té atmosféry typu "všechno co děláš je špatně, neřeknu ti proč nebo jak to udělat lépe, ale ber to tak, že to umim líp.". Nevím jestli tímto způsobem reaguješ na všechna témata, ale mně osobně to přijde až urážlivé. Chápu, že dělám něco špatně, jinak bych ostatně ani nezakládal toto téma. Doufal jsem spíše v to, že dostanu několik cenných rad a tipů od zkušenejších, ne že mi někdo zopakuje to, že dělám něco špatně a to na několika řádcích textu.
Jan Tvrdík
Profil
Someone:
Pro začátek dva odkazy:
forum.nette.org/cs/1276-model-a-pripojeni-k-db#p6884
www.phpguru.cz/clanky/model-neni-pouze-databaze#comment-31

Ocenil bych, když bys uvedl nějaký nástin správného řešení.
Přečti si libovolné rozumný článek o MVC (např. www.zdrojak.cz/clanky/uvod-do-architektury-mvc). Nebo se koukni, jak to třeba řeší Symfony:
symfony.com/doc/current/quick_tour/the_big_picture.html
symfony.com/doc/current/book/from_flat_php_to_symfony2.html
Someone
Profil
Jan Tvrdík:
Mnohem lepší, díky.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: