Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: web_tonda 28. 03. 2018, 11:11:54
-
Ahoj,programuji jednoduchou CRUD aplikaci, a v podstate poprve se to snazime udelat tak aby to byl REST interface, narazil jsem ale na par problemu v navrhu.
Predstavme si ze mame table Users a table Posts (fk=user.id). z takovyho schemata mi vyplynuly nasledujici controllery (jsou hodne granularni) v ramci takovych routes.
get_user_controller - "GET xxx/users/:userid"
post_user_controller - "POST xxx/users/:userid"
put_user_controller - "PUT xxx/users/:userid"
delete_user_controller - "DELETE xxx/users/:userid"
get_post_controller - "GET xxx/posts/:postid"
post_post_controller - "POST xxx/posts/:postid"
put_post_controller - "PUT xxx/posts/:postid"
delete_post_controller - "DELETE xxx/posts/:postid"
potud se to zda pekny a fajn (valna vetsina tutorialu na netu to nejak takhle prezentuje), JENZE nasleduje tahle vec - chcete udelat one-to-many relation ve smyslu users-post (pac posty maj fk k userum) - routes jsou jeste rekneme v poradku (snad?)
"GET xxx/users/:userid/posts/:postid"
"POST xxx/users/:userid/posts/:postid"
"PUT xxx/users/:userid/posts/:postid"
"DELETE xxx/users/:userid/posts/:postid"
JENZE nasleduje ten velky problem - jak na controllery? opravdu bych mel spravne napsat sadu 4 novych controlleru? neporusuje to dry, nemel bych spis mit mene controlleru a parametrizovat je vice? Co kdyz budu chtit pridat dalsi table? dalsi 4 controllery?
A ted to nejhorsi, co kdyz muj user table ma 6 one-to-many relations napriklad s tably - comments, books, movies, posts, friends, etc - musim pro kazdou takovou resource udelat 4, opakuji 4 nove controllery? to bych potom na na ten user table s 6fk tably, mel panecku 24 controlleru a 24 novych routes - neni to proboha priserne moc? neni problem to udelat ale zda se mi ze takove reseni neskaluje a co je nejhorsi v zadnym tutorialu co jsem videl okolo RESTu, i po googleni na stack overflow, nebylo vysvetelene jak tohle spravne a modularne udelat pri relacich one-to-many a many-to-many.
Chapu rest spravne? Je mozne ze to delam od zakladu blbe.
Diky za jakekoliv rady, jsem totalni novacek.
-
Mel bys mit strukturu:
user_controller
action_get
action_post
action_put
action_delete
post_controller
action_get
action_post
atd..
-
JENZE nasleduje ten velky problem - jak na controllery? opravdu bych mel spravne napsat sadu 4 novych controlleru? neporusuje to dry, nemel bych spis mit mene controlleru a parametrizovat je vice? Co kdyz budu chtit pridat dalsi table? dalsi 4 controllery?
A ted to nejhorsi, co kdyz muj user table ma 6 one-to-many relations napriklad s tably - comments, books, movies, posts, friends, etc - musim pro kazdou takovou resource udelat 4, opakuji 4 nove controllery? to bych potom na na ten user table s 6fk tably, mel panecku 24 controlleru a 24 novych routes - neni to proboha priserne moc? neni problem to udelat ale zda se mi ze takove reseni neskaluje a co je nejhorsi v zadnym tutorialu co jsem videl okolo RESTu, i po googleni na stack overflow, nebylo vysvetelene jak tohle spravne a modularne udelat pri relacich one-to-many a many-to-many.
"GET xxx/posts"
post_controller/action_get_posts -> Vypis bude vsechny zaznamy z tabulky posts
"GET xxx/users/:userid/posts"
user_controller/action_get_posts -> Vypis vsech posts pro uzivatele xy.
-
"GET xxx/posts/:postid"
"GET xxx/users/:userid/posts/:postid"
Maji tyhle dve routy vracet stejnou odpoved?
Jestli ano tak proc ta druha existuje?
Jestli ne tak potrebuju lip vysvetlit usecase.
-
"GET xxx/posts/:postid"
"GET xxx/users/:userid/posts/:postid"
Maji tyhle dve routy vracet stejnou odpoved?
Jestli ano tak proc ta druha existuje?
Jestli ne tak potrebuju lip vysvetlit usecase.
1. SELECT * from posts WHERE post_id = :postid
2. SELECT * from posts WHERE post_id = :postid AND user_id = :userid
Defakto neni nutne ten druhy delat, nicmene je beznou praxi delat vsechny CRUD endpointy
-
A co takhle?
GET /users
GET /users/:userid
GET /posts
GET /posts?userid=:userid
GET /posts/:postid
-
A co takhle?
GET /users
GET /users/:userid
GET /posts
GET /posts?userid=:userid
GET /posts/:postid
Pokud se bavime o zavislostech, takhle by to nemelo byt. Properties v GET parametrech se pouzivaji pro filtraci / razeni (tj treba GET /posts?sort=title,ASC, nebo GET /posts?filter.name=lorem*)
-
"GET xxx/posts/:postid"
"GET xxx/users/:userid/posts/:postid"
Maji tyhle dve routy vracet stejnou odpoved?
Jestli ano tak proc ta druha existuje?
Jestli ne tak potrebuju lip vysvetlit usecase.
1. SELECT * from posts WHERE post_id = :postid
2. SELECT * from posts WHERE post_id = :postid AND user_id = :userid
Defakto neni nutne ten druhy delat, nicmene je beznou praxi delat vsechny CRUD endpointy
Takze by to slo vyresit jen routovanim obou requestu na stejny controller i akci a ignorovanim userid.
API by zustalo kompletni a pocet kontroleru i akci by rostl linearne s poctem tabulek.
-
Defakto neni nutne ten druhy delat, nicmene je beznou praxi delat vsechny CRUD endpointy
Nemyslim si, ze delat vsechny CRUD je beznou praxi a uz vubec asi ne dobrou praxi. Pokud ten endpoint neni potreba, tak bych ho rozhodne nedelal.
A jeste jeden komentar. Pokud POST endpoint ma vytvaret zaznamy, tak by nemel prijimat ID jako parametr. To ID by melo byt unikatni a klient nema sanci zjistit, jaky ID je nebo neni. Beznou praxi je, aby tento endpoint vratil nejaky identifikator prave vytvoreneho zaznamu.
-
Nechceš raději použít framework, který řeší vazby a url řeší za tebe, standardním způsbem?
-
Nechceš raději použít framework, který řeší vazby a url řeší za tebe, standardním způsbem?
přesně tak....já doporučuju Ruby On Rails....sám si tím teď procházím a CRUD/REST je tam vyřešen parádně
pro člověka s programátorskými znalostmi to bude stíhačka, když to začíná chápat i taková lama jako já! :_)
-
Rails je dobrá volba. Když používáte ORM, tak máte vazby, validace atd. už popsané v modelech. API vytvoříte téměř zadarmo.
-
Koukám že tady nikdo neodpověděl tazateli na to na co se ptal - já to ještě pro jistotu jednou napíšu aby to bylo jasnější co tazatel chtěl.
když máte uri "POST xxx/users/" - je to jasný - voláte něco jako user.POST_controller
když máte uri "POST xxx/posts/" - opět je to jasný - voláte něco jako post.POST_controller
jenže když máte například získat všehny posty daného usera, uri může vypadat nějak takhle "GET xxx/users/:userID/posts", jakej controller na to z výše vyjmenovaných zavoláte? Ha? Žádnej - protože žádnej z výše uvedených tohle nedokáže zpracovat.
můžete udělat novej controller kterej bude pracovat s novým parametrem v URI, JENŽE bude tento controller z modelu User? (jasně, uri začíná "/users/:userID tak User) A NEBO ten controller bude z modelu POST, protože přece ta resource která se vrací je jen seznam vyfiltrovaných postů - a nebo uděláte úplně novej model? HA? (schválně neodpovím)
Odpovědi typu "místo microframeworků použij framework který to řeší za tebe" nebudu komentovat - očividně pracuje s frameworkem, kde si tohle má udělat sám, a pokud tomu nerozumí je to dobrá cesta se to naučit.
-
Neznám kanonickou implementaci RESTu (a určitě by stálo by se do nějaké dobré implementace podívat, ideálně za použití stejných nástrojů jako používá tazatel), nicméně to routování tam je IMHO mimo jiné taky proto, že lze více url mapovat na stejný kontroler. Jinak je otázka, zda jsou vůbec ty endpointy pro vazby potřeba? Nestačí mít entity jen pro vlastní entity a pracovat s kolekcemi?
Jinak v některých framweorcích je skutečně REST API zdarma, je generované automaticky. Tam by se šlo taky inspirovat.
-
jenže když máte například získat všehny posty daného usera, uri může vypadat nějak takhle "GET xxx/users/:userID/posts", jakej controller na to z výše vyjmenovaných zavoláte? Ha? Žádnej - protože žádnej z výše uvedených tohle nedokáže zpracovat.
můžete udělat novej controller kterej bude pracovat s novým parametrem v URI, JENŽE bude tento controller z modelu User? (jasně, uri začíná "/users/:userID tak User) A NEBO ten controller bude z modelu POST, protože přece ta resource která se vrací je jen seznam vyfiltrovaných postů - a nebo uděláte úplně novej model? HA? (schválně neodpovím)
Tazateli jsem na toto odpověděl hned na začátku.
"GET xxx/users/:userID/posts" zpracovává user_controller::action_get_posts není potřeba na to vytvářet žádný nový kontroller ani model. Opravdu není potřeba znovu objevovat kolo.
-
jenže když máte například získat všehny posty daného usera, uri může vypadat nějak takhle "GET xxx/users/:userID/posts", jakej controller na to z výše vyjmenovaných zavoláte? Ha? Žádnej - protože žádnej z výše uvedených tohle nedokáže zpracovat.
můžete udělat novej controller kterej bude pracovat s novým parametrem v URI, JENŽE bude tento controller z modelu User? (jasně, uri začíná "/users/:userID tak User) A NEBO ten controller bude z modelu POST, protože přece ta resource která se vrací je jen seznam vyfiltrovaných postů - a nebo uděláte úplně novej model? HA? (schválně neodpovím)
Tazateli jsem na toto odpověděl hned na začátku.
"GET xxx/users/:userID/posts" zpracovává user_controller::action_get_posts není potřeba na to vytvářet žádný nový kontroller ani model. Opravdu není potřeba znovu objevovat kolo.
to podle mě není REST. Správně odpověděl Natix. Url by měly být jen ve tvaru /resources nebo resources/id + nějaké parametry.
-
Pokud se bavime o zavislostech, takhle by to nemelo byt. Properties v GET parametrech se pouzivaji pro filtraci / razeni (tj treba GET /posts?sort=title,ASC, nebo GET /posts?filter.name=lorem*)
Filtrace podle user_id není filtrace?
-
jenže když máte například získat všehny posty daného usera, uri může vypadat nějak takhle "GET xxx/users/:userID/posts", jakej controller na to z výše vyjmenovaných zavoláte? Ha? Žádnej - protože žádnej z výše uvedených tohle nedokáže zpracovat.
můžete udělat novej controller kterej bude pracovat s novým parametrem v URI, JENŽE bude tento controller z modelu User? (jasně, uri začíná "/users/:userID tak User) A NEBO ten controller bude z modelu POST, protože přece ta resource která se vrací je jen seznam vyfiltrovaných postů - a nebo uděláte úplně novej model? HA? (schválně neodpovím)
Tazateli jsem na toto odpověděl hned na začátku.
"GET xxx/users/:userID/posts" zpracovává user_controller::action_get_posts není potřeba na to vytvářet žádný nový kontroller ani model. Opravdu není potřeba znovu objevovat kolo.
to podle mě není REST. Správně odpověděl Natix. Url by měly být jen ve tvaru /resources nebo resources/id + nějaké parametry.
1. Pokud se nepletu, tak autor se neptal na to, co je a není RESTful, ale jak vytvářet MVC pattern vůči jednotlivým
routes.
2. RESTful API se nedefinuje tím, jakým způsobem se předávájí parametry v URL. I když existují good practises i v tomto směru, které podporují to co jsem napsal.
https://stackoverflow.com/questions/671118/what-exactly-is-restful-programming
https://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/
a tak dale...
-
když máte uri "POST xxx/users/" - je to jasný - voláte něco jako user.POST_controller
když máte uri "POST xxx/posts/" - opět je to jasný - voláte něco jako post.POST_controller
jenže když máte například získat všehny posty daného usera, uri může vypadat nějak takhle "GET xxx/users/:userID/posts", jakej controller na to z výše vyjmenovaných zavoláte? Ha? Žádnej - protože žádnej z výše uvedených tohle nedokáže zpracovat.
Závolá se user.POST_controler s filtrem, že se mají vrátit posty.
To url mi přijde ošklivé, takové neRESTové.
A už tu bylo řečeno, že POST by měla být akce kontroleru (respektive dá se to rozdělit, ale ne mechanicky podle metod).