ugrás a tartalomhoz

MVC kérdés: blog modell-jének kialakítása

Max Logan · 2008. Nov. 11. (K), 02.28
A probléma a következő: adott egy MVC rendszer, amivel megvalósítunk egy blog-ot. A blog modell-jének van egy olyan metódusa, mely visszaadja az utolsó X bejegyzés adatait, melyek a következők: cím, bevezető rész, hosszabb rész, dátum, szerző, cimkék.

A kérdés pedig a következő, logikailag hogyan érdemes megoldani azt, hogy a cimkéket is lekérjük?

1. Legyen egy függvény, mely visszad minden információt az bejegyzésekről:
  • Lekéri az utolsó X bejegyzést
  • Kigyűjtögeti mindegyikhez a cimkéket
  • A cimkéket hozzáadja a megfelelő post-hoz (amit egy tömb reprezentál)
  • Visszaadja a post minden adatát
Itt kétfelé ágazik el a dolog:
  • lehet egy olyan metódusa a modell-nek, ami a kapott ID-jű post-hoz tartozó cimkéket adja vissza
  • a cimkelekérést a függvényen belül oldajuk meg külön függvény felhasználása nélkül

2. Legyen egy függvény, mely visszaadja a bejegyzések infóit, kivéve a cimkéket


A működése ugyanaz, mint fentebb, kivéve, hogy a cimkéket nem kéri le.

A cimkelekérdezést az előbb leírt módon egy külön modell metódust hajtja végre, melyet a kontroller hivogat.

A három megoldás közül melyik a célszerűbb?

Az első szerintem a legtisztább logikai szempontból, mert egyszerre megkap a kontroller minden infót az egyes bejegyzésekről. A cimkék lekérést megvalósító külön modell metódus letisztultabbnak látszik, a nagy metódushoz képest (áttekinthetőbb lesz a fő metódus).

A második megoldás végülis az első különválasztása, mely nem tudom, hogy mennyire szerencsés, azaz érdemes-e a kontrollerre bízni, hogy külön kérje le az egyes bejegyzések cimkéit.
 
1

DB

vbence · 2008. Nov. 11. (K), 03.12
Az adatbázisnak egy group_concat végrehajtása lényegesen egyszerűbb, mint külön lekérdezéseket futtatni.

Ha foglalkozol ilyen dolgokkal, akkor én azt ajánlom próbálj ki egy ORM-et. Szerintem nem jó ráerőltetni az MVC-t egy projektre, pusztán az MVC kedvéért.
2

A cimkék nem szövegként ...

Max Logan · 2008. Nov. 11. (K), 10.16
... vannak kezelve, hanem linkek az egyes cimkék alapján szűrt bejegyzés listára, így a group_concat nem jó nekem, mert kell a cimke neve és az adatbázis ID-ja is.

Ami az ORM-et illeti, tervezem, hogy meglesem hogyan működik (az eddigi WL-es topic-ok alapján nem szimpi), de a mostani project-ben biztoan nem fogom még használni (így is jelentős csúszásban vagyok vele).
4

group concat

vbence · 2008. Nov. 11. (K), 12.22
Lehet két group_concat, csak ugyanarra legyenek rendezve:
... GROUP_CONCAT(tag.id ORDER BY tag.word) AS tids,
GROUP_CONCAT(tag.word ORDER BY tag.word) AS twords
vagy kifejezés a group concatban:
... GROUP_CONCAT(CONCAT(tag.id, ':', tag.word) ORDER BY tag.word) AS tags
bármelyik esetben egy explode megoldja akicsomagolást.
3

kapcsolat?

Hodicska Gergely · 2008. Nov. 11. (K), 12.18
Eredeti kérdés: szerintem a modell dolga, hogy a megfelelő formában biztosítsa az adatokat. Az hogy ezt hogyan oldod meg, az már egy másik kérdés, alapvetően egyik említett megoldás sem tetszik. Ha mindig kell cimke, és csak pár sorrol van szó, akkor valszeg az optimális megoldás simán egy join. Ha nem akkor csinálhaszt két metódust: getLastEntries és getLastEntriesWithTags.

Ha foglalkozol ilyen dolgokkal, akkor én azt ajánlom próbálj ki egy ORM-et. Szerintem nem jó ráerőltetni az MVC-t egy projektre, pusztán az MVC kedvéért.
Ez a mondat nem igazán értelmezhető szerintem: ORM vs MVC? Az ORM az az M része, még csak nem is az egész, jelen kérdés felvetés szempontjából szerintem nem lényeges.

group_concat nem jó nekem, mert kell a cimke neve és az adatbázis ID-ja is
implode() ;) (izé, explode :D)
5

Re

Max Logan · 2008. Nov. 11. (K), 14.14
Minden esetben kell cimke. A függvény az utolsó 10 post-ot adja vissza, amit aztán a blog kezdőlapján jelenítünk meg.

Jelenleg egyébként úgy működik, hogy lefut egy query a getLastPosts() függvényben, ami lekéri az utolsó 10 post-ot, majd egy másik qruery, ami lekéri az egyes post-okhoz tartozó cimkéket (ID-t és nevet a tags táblából a tag_relationship tábla segítségével), majd a cimkéket tartalmazó tömböt beteszem a $posts[i]["tags"] változóba.

Amit szeretnék:

POSTS táblából lekérni: id, title, preview, details, date
AUTHORS táblából: name
TAGS táblából: name (rájöttem, hogy az ID nem kell, mert a tag nevére linkelek, nem ID-ra)

Táblák

POSTS - id, title, preview, details, date, author_id
TAGS - id, name
TAG_RELATIONSHIP - post_id, tag_id
AUTHORS - id, name

Hogyan oldaható meg a legoptimálisabban, hogy visszakapjam az utolsó 10 post-ot dátum szerint csökkenően rendezve, a megadott adatok alapján (a tag-ek lehetnek összefűzve)?

Nem vagyok egy SQL guru, tehát én csak 2 lekéréssel tudom megoldani, amit fentebb le is írtam.
6

Látom, kárhozatra ítélted a negyedik posztot :)

vbence · 2008. Nov. 11. (K), 15.06
... amiben két példa is van, hogyan lehet egy queryben elintézni a dolgot.
8

Nem ítéltem, de ...

Max Logan · 2008. Nov. 11. (K), 18.48
... nem értem, hogy a GROUP_CONCAT-et hogyan tudnám felhasználni úgy, hogy egy query-ben lefusson, ne kelljen 2 query-t csinálni. Nálam azért van ugye a második query, mert M:N kapcsolat van a post-ok és a tag-ek között (ha eddig nem derült volna ki, egy post-hoz tetszőleges számú tag csatolható).
9

Valahogy így...

vbence · 2008. Nov. 11. (K), 20.27
SELECT posts.id, posts.title, posts.preview, posts.details, posts.date,
 GROUP_CONCAT(tags.name ORDER BY tags.name) AS tids,  
 GROUP_CONCAT(tags.name ORDER BY tags.name) AS tnames,
 authors.name AS aname
FORM posts
 LEFT JOIN tag_relationsip ON tag_relationsip.post_id = posts.id
 LEFT JOIN tags ON tags.id = tag_relationsip.tag_id
 LEFT JOIN authors ON authors.id = post.author_id
GROUP BY posts.id
ORDER BY posts.date DESC
LIMIT 10
Persze lehet, hogy van benne hiba...

Jól szemlélteti viszont a "többeszám" elnevezési konvenció hiányosságát:
authors.id = author_id

mennyivel szebben fest:
author.id = author_id

vagy esetleg:
author.id = post.author

De persze mindenkinek a saját édesanyja alegszebb :)
10

Thx

Max Logan · 2008. Nov. 11. (K), 21.09
Ezer köszönönet, így már működik a dolog. Azt hiszem kicsit rá kell feküdnöm az SQL-re, mert a megoldás végülis egyszerű, és logikus (csak én nem SQL logikával indultam el ...).
11

javítás

vbence · 2008. Nov. 11. (K), 22.21
Az SQL második sora helyesen:
GROUP_CONCAT(tags.id ORDER BY tags.name) AS tids
13

nem szabványos query

Hodicska Gergely · 2008. Nov. 12. (Sze), 00.41
Arra érdemes figyelni, hogy MySQL-en kívül nem sok minden eszi meg ezt a queryt. Már előjött itt is párszor: group by esetén a csoportosításban nem részt vevő mező nem szerepelhet a select listben önmagában, csak aggregátor függvényen belül.
15

Szabványosan?

Max Logan · 2009. Jan. 12. (H), 22.39
Bár nekem csak MySQL-re kell, de elméleti kérdésként: hogyan van a fenti query szabványosan, ami minden SQL szerveren lefut (már ha egyáltalán van erre szabványos megoldás egy query-vel)?
16

aggregátor függvény

Hodicska Gergely · 2009. Jan. 13. (K), 03.01
A nem groupolt mezőknek aggregátor függvényen belül kell lenniük. Ez a query valahol egy nem túl szerencsés eset, mert a post részből adódó mezők esetén minden sorban ugyanaz lesz mondjuk a cím, így ebben a formában tudsz mondjuk egy olyat, hogy azt mondod, hogy max(title).

De mint sok esetben a programozásban, ha valamit nem tudsz "szépen" megcsinálni, akkor ott jó eséllyel nem jó a megközelítés: jelen esetben is nem biztos, hogy szerencsés a cikkek adatait a tagekkel együtt lekérdezni. Vonzó, hogy egy lekérdezéssel megvan, de pl. ha 100 cikket szeretnél így lekérdezni, és mindegyiknek van mondjuk átlag 5 tagje, akkor már ez a megközelítés jelentősen növeli az eredményhalmaz méretét.
17

Sejtettem ...

Max Logan · 2009. Jan. 13. (K), 12.24
... hogy ez a megközelítés, bár "kényelmes", nem éppen ideális. Megnéztem a WordPress forrását, ott is külön oldják meg a post adatainak lekérését és a tagek kigyűjtését.
7

orm és az m

vbence · 2008. Nov. 11. (K), 17.10
Akármennyire is gyerek cipőben járnak az ORM-ek, megadják a "hookokat" az ehhez hasonló igények fájdalommentes beépítésére. Én úgy tekintem, hogy a model megalkotására nyújt egy épkézláb lehetőséget.

Persze lehet ORM nélkül is, interfészek definiálásával, szépen, csak kérdés, hogy a postok 6 féle nézetére (főoldal, szerző főoldala, tag szerinti listázás, "legfrissebb" box stb stb) - ahol más-más mezőkre vagyunk kíváncsiak szeretnénk-e 6 különböző interfészt létrehozni.

Pl:
interface ShortPost {
    getTitle, getAuthor, getDate
}

interface Post implements ShortPost {
    getLead
}

interface Tagged {
    getTags
}

interface TaggedPost implements Post, Tagged {
}

class PostTable {
    public Post[] getLastPosts() {
    }

    public TaggedPost[] getLastPostsWithTags() {
    }

    public ShortPost[] getLastPostsShort() {
    }
}
Persze lehet, hogy így kéne csinálni :)
12

???

Hodicska Gergely · 2008. Nov. 12. (Sze), 00.35
Akármennyire is gyerek cipőben járnak az ORM-ek, megadják a "hookokat" az ehhez hasonló igények fájdalommentes beépítésére.
Ezt szerintem alapból tudja egy ORM, akár úgyis, hogy "lazy" módon szedi le a tageket, akár úgyis, hogy egyből.

Persze lehet ORM nélkül is, interfészek definiálásával
Sajnos nem értem, hogy mire gondolsz, hogy jönnek ide az interfészek.

Az eredeti felvetéssel nekem az volt a bajom, hogy nem lehet az MVC-t párhuzamba állítani az ORM-mel ("használj MVC helyett ORM-et"), nem egy "szinten" vannak. Az MVC-ből az ORM az M betű egy része.
14

Akkor pontosítok

vbence · 2008. Nov. 12. (Sze), 01.32
Én nem írtam olyat, hogy MVC helyett ORM (bár bizonyos aspektusból akár ez is megállná a helyét).

Amire gondoltam az, hogy az általa vázolt eljárásoknál egy ORM általában jobb lehetőségeket ad.

Az ORM egy eszköz, az MVC egy fejlesztési stratégia. Ha MVC-t használunk, akkor az ORM a modell része. Viszont egy ORM használható anélkül is, hogy az MVC stratégiával élnénk.
18

Modell vagy nem modell, ez itt a kérdés

Max Logan · 2009. Aug. 25. (K), 21.13
Van megint egy kis dilemmám a modellel, bár nem teljesen kapcsolódik a fenti kérdéshez.

Az utóbbi időben már elég jól be tudom lőni, hogy mi kerüljön a modellbe és mi maradjon a kontrollerben, de a következő dolog kifogott tarjtam.

Tehát adott egy getPostList action. A getPostList azt csinálja, hogy megjelenít bizonyos számú bejegyzést, megfűszerezve azzal, hogy lapozhatóságot valósít meg. Azaz első körben mondjuk az utolsó 10 bejegyzést jeleníti meg, aztán ha úgy alakul, akkor a korábbi bejegyzések közül 10 darabot.

Namost jelenleg ebben az action-ben van megvalósítva az előző és következő oldalra mutató link előállítása. A dilemmám az, hogy egy ilyen link előállítása a kontroller vagy a modell feladata?

Ha abból indulok ki, hogy a kontroller funkcionalitása korlátozódik az adatok összegyűjtésére, azok validálására, a modellel való oda-vissza kommunikációra (adatok szolgáltatása a modellnek, adatok kérése a modelltől), valamint a nézetek kezelésére, akkor nem illik a képbe két ilyen link előállítása.

Ki hogy látja, a kontroller vagy a modell feladata előállítani a lapozásért felelős linket?
19

Adat

Ustak · 2009. Aug. 25. (K), 23.00
Egyfajta vélemény szerint, amit idegen nyelven olvastam valahol, a modell nem csak az adatbázisból kinyert adatokkal kell hogy dolgozzon, de ide tartozik az egyéb adatok kezelése is (pl session) és ilyenformán szerintem a modellhez tartozik a link érdemi adatrészének előállítása is.
Szóval szerintem modell.
Üdv:
Gábor.
23

Adat forrás

Max Logan · 2009. Szep. 20. (V), 14.13
Nos, ha pl. a session-ből és a cookie-ból származó adat is a modell része, akkor ilyen esetben hogyan történik meg az adatvalidálás?

Azaz van mondjuk egy cookie-ban tárolt adat, amiről azért ellenőrizni kellene, hogy megfelel-e a formai követelményeknek. Ezen ellenőrzés a modell vagy a kontroller feladata? Vagy a cookie az nem a modell része, hanem bejövő adat és így a kontrollernek kell validálnia?

Ha nem megfelelő az adat formája (pl. xyz karakterek lehetnek csak benne, de van benne m karakter is) és a modell részének tekintjük, akkor mi történik? Mert a modell nem szólhat vissza, hogy bocsi nem megfelelő az adat, mert ez kb. olyan, mint amikor valaki az adatbázisban kézzel írja át a kérdéses adatot.

Szerk.: Belegondolva, mivel a kéréssel együtt érkezik a cookie-ból az adat, ezért bejövő adatnak érdemes tekinteni. Ergó úgy kezeljük, mint ha GET paraméterként érkezne, így pedig a kontroller validálja.
20

van egy reteg

carstepPCE · 2009. Aug. 26. (Sze), 12.30
van egy reteg, amirol az mvc modellben nagyon surun elfeledkeznek, ez pedig a model(ek) es a controller kozott huzodik. Ez tartalmazza az uzleti logikat, es altalaban sokan itt vannak meglove, hogy ez most a modelbe tegyek e vagy a controllerbe. Igazabol elmeleti kerdes, de vastag model hasznalata eseten, ugye az uzleti logika a modelbe kerul bele.

Nekem altalaban csak 1 kerdes szokott felmerulni, mi van ha 1xre tobb modellel is dolgoznom kell egy adott uzleti logika megvalositasahoz?

-cs-
Sanyi
21

Abstract osztály, extends

Poetro · 2009. Aug. 26. (Sze), 13.28
Abstract osztály, közös szülő osztály, ilyesmik.
22

...

carstepPCE · 2009. Aug. 26. (Sze), 16.28
extends-sel az a baj, hogy serul a zartsaga az osztalynak, absztrakt osztaly helyett meg inkabb interface fele kell programozni, de ezek meg mindig nem oldjak fel a model es uzleti logika kozotti rest :(

-cs-
Sanyi