Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]redirect() i forward()
Forum PHP.pl > Forum > PHP
marcio
Witam od czasu do czasu przez ucho owinie mi sie cos na temat forward() i redirect().

Z tego co mi wiadomo i co dalem rade wygrzebac z symfony i zf to redirect() to zwykle przekierowanie za pomoca header/meta fresh'a na dany kontroler i jego akcje z przeladowaniem strony.

A forward() to nastepna akcja do odpalenia bez przeladowania strony.

No i teraz pytanie gdzie i jak tego uzywac?
Powiedzmy ze redirect() wiem jak zaimplementowac i po co ale forward() nie wiem nawet po co a o tym jak to juz nie wspomne.

Tak zeby juz nie zakladac nastepnego watku mam tez pytanie dotyczace zasad routingu ostatnio byl temat na forum o tym ze np routes wyglada tak:
Cytat
/:Lang/:controller/:action

I do tego cala implementacja na podstawie tego configu jednak nie wiedzialem po co tak kombinowac u mnie mma na stale przy url:
Cytat
index.php/Home,Index,ShowAllNews

Frontcontroller = Home
Action Frontcontrollera = Index
Akcja komponentu/pluginu = ShowAllNews.

Ogolnie jezyk w moim fw wybiera sie defaultowo przy tworzeniu obiektu klasy Language ktory jest zapisywany do cookie lub za jak ktos chce moze zrobic maly form lub flagi z akcja i przekazac jezyk do metody setLang() ktora ustawi jezyk.

Jednak nie byloby glupie gdybym mogl sobie zmienic tak router by moc miec 2 mozliwosci:
Cytat
/:controller/:action/:cpaction

Lub:
Cytat
/:lang/:controller/:action/:cpaction

I wtedy zamiast poprzez form/flagi zapisywac lang z 1 parametru url'a.

Jednak nie wiem zabardzo jak to zautomatyzowac by za pomoca zasad routingu Router robil wszystko automatycznie.
Jesli ktos chce moge mu podac klase Router wtedy mi podpowie.
Crozin
Ten FW jest do Twojego użytku? To po co chcesz w nim implementować coś z czego nawet nie będziesz korzystać?

1) Przykład zastosowania forward z symfony? Powiedzmy, że mamy akcje wyświetlania czegoś z bazy - np. profil użytkownika. Ktoś podaje adres, ale okazuje się, że użytkownika o podanym ID nie ma, więc co robimy? Wyświetlany błąd 404, czyli wykonujemy forwarda do akcji 404. Inny przykład: mamy ankiety. Ktoś wypełnia ją, formularz jest wysyłany, głos dodany, a nam ma się wyświetlić wynik ankiety (po uwzględnieniu naszego głosu). No to robimy forwarda na akcję wyświetlającą wyniki danej ankiety.
2) O ilę się nie mylę w symfony jest to zrobione tak, że forward wyrzuca wyjątek typu ABCzrobForwarda. Nie wiem dokładnie jak to jest zrobione, ale mogłoby to wyglądać tak:
  1. <?php
  2.  
  3. try{
  4. $this->executeAction($modulZRoutera, $akcjaZRoutera);
  5. }catch(ForwardException $e){
  6. $this->executeAction($e->getMode(), $e->getAction());
  7. }

3) IMO zapisywanie reguł w formie
Kod
/:Lang/:controller/:action
Jest bez sensu (przynajmniej w symfony). Lepiej jest odpowiednio zmodyfikować klasę route-ingu, tak by automatycznie dodawała/rozpoznawała czy istnieje fragment dot. języka - w końcu jest to używane na każdej podstronie. Chociaż w sumie najlepiej to język wepchać jako subdomenę - napewno nie jako cookie - nie można wtedy podesłać znajomemu linka w normalnym (dla niego) języku.
marcio
Cytat
1) Przykład zastosowania forward z symfony? Powiedzmy, że mamy akcje wyświetlania czegoś z bazy - np. profil użytkownika. Ktoś podaje adres, ale okazuje się, że użytkownika o podanym ID nie ma, więc co robimy? Wyświetlany błąd 404, czyli wykonujemy forwarda do akcji 404. Inny przykład: mamy ankiety. Ktoś wypełnia ją, formularz jest wysyłany, głos dodany, a nam ma się wyświetlić wynik ankiety (po uwzględnieniu naszego głosu). No to robimy forwarda na akcję wyświetlającą wyniki danej ankiety.


No to forward() juz wiem przekierowanie do jakiegos kontrolera/akcji gdy cos poszlo nie tak lub bo jakie zmianach mnie wiecej ogoonie wiem o co kaman.




A redirect() w tym przypadku bo nie wiem?




Co do subdomen to masz racje ale na darmowych srv owych nie ma a z tym tez trzeba sie liczyc smile.gif.




Cytat
Jest bez sensu (przynajmniej w symfony). Lepiej jest odpowiednio zmodyfikować klasę route-ingu, tak by automatycznie dodawała/rozpoznawała czy istnieje fragment dot. języka - w końcu jest to używane na każdej podstronie


Racja zaduzo kombinowania by z tym bylo lepiej dac 2 opcje jezyk w cookie lub w url i zintegrowac klase router z lanuage by ze soba wspolpracowaly dzis to dokoncze i pokaze jak ktos bedzie chetny by zobaczyc.




Crozin
Cytat
Co do subdomen to masz racje ale na darmowych srv owych nie ma a z tym tez trzeba sie liczyc
Że tak powiem... nie bądź śmieszny. winksmiley.jpg

EDIT: forward - serwer sobie robi przekierowanie, redirect - użytkownik zostaje przekierowany na inny adres.
EDIT2: vokiel to ładnie ujął
vokiel
No chyba jest to trochę inaczej. Różnica jest niewielka. Ogólnie rzecz biorąc opiera się na:
forward odnosi się do części aplikacji i jest transparentne dla użytkownika, adres pozostaje taki sam,
redirect jest bardziej dla przeglądarki niż systemu (aplikacji www), powoduje wywołanie nowego requesta, zmienia url w pasku adresu

Czyli forward jest wewnątrz aplikacji, np przekazanie działania do innej metody, klasy (niewidoczny dla użytkownika).
Natomiast redirect jest właśnie dla użytkownika, przenosi go jawnie na inny adres url.
marcio
Forward mozna uzyc gdy dodajemy posta lub komentarz do jakiegos news'a wtedy by go zobaczyc strona musi sie przeladowac robimy forward() na taki sam adres.




A redirect jestesmy na stronie:

Cytat
index.php/Home,Index,ShowProfil,2


Wysiwetlamy profil user'a o id 2 np klikamy na logout i robie redirect na index.php i tyle?




Dobrze zrozumialem?

Jesli nie to prosze o jakis praktyczny przyklad.

batman
1. Redirect - przekierowanie do innej akcji. Najlepszy przykład - jesteś na formularzy edycji użytkownika, zapisujesz dane do bazy, następuje redirect, czyli "kliknięcie" w nowy adres.
2. Forward - przekazanie sterowania do innej akcji. Najlepszy przykład - autoryzacja - chcesz wejść na jakąś stronę, ale zamiast treści pokazuje Ci się formularz logowania, mimo, że adres wskazuje na tą treść, np artykul-123.html. Dopiero jak się zalogujesz będziesz mógł przeczytać treść. Forward spowodował, że sterowanie przekazano do akcji logowania, bez konieczności przeładowania strony.
marcio
Cytat
1. Redirect - przekierowanie do innej akcji. Najlepszy przykład - jesteś na formularzy edycji użytkownika, zapisujesz dane do bazy, następuje redirect, czyli "kliknięcie" w nowy adres.


A nie rediretc() na referer?

A jak na nowy adres tzn np?




Cytat
2. Forward - przekazanie sterowania do innej akcji. Najlepszy przykład - autoryzacja - chcesz wejść na jakąś stronę, ale zamiast treści pokazuje Ci się formularz logowania, mimo, że adres wskazuje na tą treść, np artykul-123.html. Dopiero jak się zalogujesz będziesz mógł przeczytać treść. Forward spowodował, że sterowanie przekazano do akcji logowania, bez konieczności przeładowania strony.


krotko mowiac przykladowy kod:

  1.  
  2. public function ShowNews() {
  3.  
  4.  
  5.  
  6.  
  7.   if($auth -> isLogged()) {
  8.  
  9.     //wyswietlamy news'a
  10.  
  11.   }
  12.  
  13.   else {
  14.  
  15.     //zamiast ladowac kontroler logowania i wywolac metode Auth()
  16.  
  17.   //wywolujemy forward() z parametrami
  18.  
  19.   /*
  20.  
  21.    wczytyujemy klase authorization i wykonujemy metode Auth czyli logowaniem, ta metoda zwraca na true i      robimy redirect() na referer
  22.  
  23.   */
  24.  
  25.  
  26.  
  27.  
  28.   if($this -> forward('Authorization', 'Auth')) {
  29.  
  30.    this -> redirect('referer');
  31.  
  32.   }
  33.  
  34. //jesli nie zalogowano znow pokazujemy akcje logowania
  35.  
  36.  else {
  37.  
  38.   $this -> forward('Authorization', 'Auth')
  39.  
  40.  }
  41.  
  42.  
  43.   
  44. }
  45.  
  46.  


Dobrze kumam?

Sorki ze tak lamersko pytam ale wydaje mi sie to przydatne a nie chcielam wynajdowywac kola na nowo i dlatego tak dokladnie pytam.

P.S ktorko mowiac forward() pozwala nam na wykonanie danego komponentu/pluginu wewnatrz innego.
Crozin
  1. <?
  2.  
  3. public function showNews(){
  4. if(/* jest niezalogowany */){
  5. $this->forward('Auth', 'signin');
  6. }
  7.  
  8. //wyswietlanie newsów
  9. }
marcio
No czyli tak jak pokazalem jest good.

Dzis sprobuje to zaimplementowac potestuje i jak cos zwroce sie do was ogolnie macie + smile.gif.









Witam zrobile juz redirect() i forward() jednak mam jeden problem z forward().
Bazujac sie na przykladzie @batman mam komponents upload ktory jest ladowany.
Jego kontroler ma defaultowa funckje Index() ktora sie wywoluje sie na samym poczatku(chyba ze w url jest podana inna metoda do wykonania) ma ona za zadanie wyswietlic formularz uploadu i po submitowaniu forma przekierowac na:
Cytat
index.php/Home,Index,Upload

I wszystko dziala pliki sue uploaduja.

Jednak teraz chce zrobic tak ze trzeba byc zalogowanym by uploadowac pliki w przeciwnym wypadku pokazuje laduje komponent Auth za pomoca forward gdy user sie zaloguje to widzi zamiast Logowania form do upload'u:
Tak wyglada funkcja Index() z kontrolera komponentu Uploader:
  1. public function Index() {
  2.  
  3. if($this -> auth -> isLogged()) {
  4.  
  5. $user = $this -> auth -> GetUserType();
  6. return $this -> view -> Layout('Uploading', 'component', $user);
  7.  
  8. }
  9.  
  10. else {
  11.  
  12. return $this -> Forward('Auth'); // gdy nie zalogowany wlaczam komponent Auth z funkcja Index()
  13.  
  14. }
  15.  
  16.  
  17. }

A tu implementacja Forward()
  1. public function Forward($ctrl, $action = 'Index') {
  2.  
  3. if(file_exists(DIR_PLUGINS_CTRL.$ctrl.'.php')) {
  4.  
  5. require_once(DIR_PLUGINS_CTRL.$ctrl.'.php');
  6.  
  7. }
  8.  
  9. else if(file_exists(DIR_COMPONENTS_CTRL.$ctrl.'.php')) {
  10.  
  11. require_once(DIR_COMPONENTS_CTRL.$ctrl.'.php');
  12.  
  13. }
  14.  
  15. if(class_exists($ctrl)) {
  16.  
  17. $forwardObj = new $ctrl();
  18.  
  19. if(method_exists($forwardObj, $action)) {
  20.  
  21. return $forwardObj -> $action();
  22.  
  23. }
  24.  
  25. }
  26.  
  27. return false;
  28.  
  29. }
  30.  

Ale jest jedno ale wszystko dziala tylko GDY na stronie mam tak czy siak zaladowany komponent Auth gdy go nie ma owszem Form logowania sie pokazuje ale jak juz kilkamy na Login i zostajemy przekierowani na:
Cytat
index.php/Home,Index,Auth

To nas nie loguje nic sie nie dzieje.
Gdy komponent logowania jest zawsze i do tego w komponencie uploadu gdy ktos nie jest zalogowany widac formularz logowania moge sie zalogowac poprzez samo komponent Auth jak i poprzez form wygenerowany przez Upload.

Gdy usune ze strony komponent Auth widzimy formularz ale sama akcja logowania nie dziala.

http://marcio.ekmll.com/index.php
Tutaj jest testowa strona gdzie testuje wszystko z mojego fw wiec nie patrzcie na wyglad poprostu zrobilem przyklad by mozna bylo zobaczyc online co jest nie tak.
Na stronie mamy komponent Auth(1 formularz), i komponent Upload(2 formularz pokazuje sie on bo nie jestesmy zalogowani).

Zalogowac mozna sie poprzez obydwa formularze i zobaczymy upload jednak gdy usune pierwszy formularz logowania(komponent Auth) jest form ale nie da sie zalogowac.

Co jest zle.

P.S ale dlugi post ale musialem wszystko dokladnie opisac.

P.S2 Zalogujcie sie za pomoca login: marcio i haslo: marcio

OK rozwiazalem wszystko.

Poniewaz moj system wczytuje komponenty/pluginy z bazy i wykonuje na nich odpowiednie metody robiac foward() wczyta sie pierwsza metoda jesli jednak w systemie dany komponent nigdzie nie zostal zaladowany druga metoda ktora jest np w method="" atrybutu form sie nie wykona bo nie znajdzie zadnego komponentu z taka metoda.

Wiec mam 3 rozwiazania mozna jest stosowac wszystkie zaleznie od sytuacji:
1)Gdy komponent jest zawsze ladowany np logowanie wydaje mi sie ze jest prawie zawsze albo form albo panle po zalogowaniu
Robimy tak jak pokazalem wyzej:
  1. public function Index() {
  2.  
  3. if($this -> auth -> isLogged()) {
  4.  
  5. $user = $this -> auth -> GetUserType();
  6. $html = $this -> view -> Layout('Uploading', 'component', $user);
  7.  
  8. }
  9.  
  10. else {
  11.  
  12. return $this -> Forward('Auth'); //Wczytujemy komponent Auth z metoda Index
  13.  
  14. }
  15.  
  16. }
  17.  

2)Gdy komponent nie jest zawsze wczytywany lub w ogole to robimy to na 2 sposoby:
  1. public function Index() {
  2.  
  3. if($this -> auth -> isLogged()) {
  4.  
  5. $user = $this -> auth -> GetUserType();
  6. $html = $this -> view -> Layout('Uploading', 'component', $user);
  7.  
  8. }
  9.  
  10. else {
  11.  
  12. $html = $this -> Forward('Auth'); //Wczytujemy komponent Auth z metoda Index
  13.  
  14. if(isset($_POST['log'])) { //Jesli wyslano form logowania
  15.  
  16. $this -> Forward('Auth', 'Auth'); // wykonujemy akcje logowania
  17. }
  18. }
  19.  
  20. return $html;
  21.  
  22. }

Albo mozna tak zaimplementowac metode Index/Auth by wyswietlala form i zarazem logowala zaleznie od tego czy ktos jest zalogowany lub nie jak nie jest wyswietla form i pootem loguje jesli go wyslano jak jest zalogowany albo panel albo nic tongue.gif

Moze troche przekombinowane ale wazne ze dziala i idea jest taka sama jak w innych fw.
Crozin
Tak, ale implementacja tego jest beznadziejna.

Tutaj bardzo prymitywny przykład (pisany na baaaaardzo szybko - bo już spóźniony jestem :])
  1. <?php
  2.  
  3. class MyForwardException extends Exception{
  4. protected $module, $action;
  5.  
  6. public function __construct($module, $action){
  7. $this->module = $module;
  8. $this->action = $action;
  9. }
  10.  
  11. public function getModule(){
  12. return $this->module;
  13. }
  14.  
  15. public function getAction(){
  16. return $this->action;
  17. }
  18. }
  19.  
  20. abstract class controller{
  21. protected function forward($module, $action){
  22. throw new MyForwardException($module, $action);
  23. }
  24. }
  25.  
  26. class newsController extends controller{
  27. public function index(){
  28. var_dump('newsController:index - przed');
  29.  
  30. if(mt_rand(0, 1) == 1){
  31. $this->forward('calendar', 'preview');
  32. }
  33.  
  34. var_dump('newsController:index - po');
  35. }
  36. }
  37.  
  38. class calendarController extends controller{
  39. public function preview(){
  40. var_dump('previewController:index');
  41. }
  42. }
  43.  
  44. class abc{
  45. public function def($module, $action){
  46. try{
  47. $ctrlName = $module . 'Controller';
  48. $ctrl = new $ctrlName;
  49. $ctrl->$action();
  50. }catch(MyForwardException $e){
  51. $this->def($e->getModule(), $e->getAction());
  52. }
  53. }
  54. }
  55.  
  56. class ghi{
  57. public static function main(){
  58. $module = 'news';
  59. $action = 'index';
  60.  
  61. try{
  62. $abc = new abc();
  63. $abc->def($module, $action);
  64. }catch(Exception $e){
  65. die('cos sie nie udało');
  66. }
  67. }
  68. }
  69.  
  70. ghi::main();
marcio
Nie rozumiem czemu jest do dupy dziala tak samo implementacja zalezy od programisty wiec moze mi wytlumaczysz co jest nie tak?

Bo dzialanie jako takie jest takie same smile.gif
Crozin
1) Forward, nie przerywa pracy aktualnej akcji
2) DRY - w forwardzie powtarzasz się (metoda wywoływania danej akcji)
marcio
Cytat
1) Forward, nie przerywa pracy aktualnej akcji

Gdzie ja przerywa?Bo ja nie wiem.

Ad 2 nie rozumie kompletnie o co kaman tongue.gif, moze jasniej?

EDIT:
  1. else {
  2.  
  3. $html = $this -> Forward('Auth'); //Wczytujemy komponent Auth z metoda Index
  4.  
  5. if(isset($_POST['log'])) { //Jesli wyslano form logowania
  6.  
  7. $this -> Forward('Auth', 'Auth'); // wykonujemy akcje logowania
  8. }
  9. }

Zapewnie chodzi o ten fragment kodu tak jak napisalem akurat przykladowy komponent logowania zaimplementowalem tak jak zaimplementowalem, jesli to zmienie wszystko bedzie good lub gdy dany komponent jest zawsze na danej stronie tak samo, zreszta jak bys przeczytal dokladnie moj post nr 10 od EDIT'a to jest tam wszystko napisane.
-=Peter=-
Cytat
Cytat

1) Forward, nie przerywa pracy aktualnej akcji

Gdzie ja przerywa?Bo ja nie wiem.

@Crozin miał na myśli, że forward powinien przerywać działanie akcje i natychmiast przekierować do następnej. Tak to jest w symfony, w ZF jest inaczej, forward nie przerywa działania akcji tylko dodaje do łańcucha akcji kolejną. Podsumowywując: forward nie musi przerywać akcji, zrób jak ci wygodniej, ale ta implementacja którą dałeś jest bardzo biedna, ona nie przekierowywuje do akcji tylko wywołuje odpowiednią metodę innego kontrolera wewnątrz innej (w środku) akcji, a to jest różnica. W twojej implementacji gdy zrobisz forwarda nie zmieniasz widoku, nie przekazujesz parametrów żądania do kontrolera akcji (żądanie nie jest chyba singletonem w twoim przypadku? nie widze jego przekazania) itp. Forward to nie tylko "wywołanie metody akcji jakiegoś innego lub tego samego kontrolera".
marcio
Cytat
W twojej implementacji gdy zrobisz forwarda nie zmieniasz widoku, nie przekazujesz parametrów żądania do kontrolera akcji (żądanie nie jest chyba singletonem w twoim przypadku? nie widze jego przekazania) itp. Forward to nie tylko "wywołanie metody akcji jakiegoś innego lub tego samego kontrolera".

Ok thx.
Przegladalem symfony i zf ale jest to tam zabardzi zagmatowane.

Moze macie jakies wlasne implementacje forward() ktora moglibyscie mi pokazac?

EDIT:
Cytat
W twojej implementacji gdy zrobisz forwarda nie zmieniasz widoku

Widok jest zmieniany poprzez akcje z danego kontrolera.

Cytat
nie przekazujesz parametrów żądania do kontrolera akcji (żądanie nie jest chyba singletonem w twoim przypadku? nie widze jego przekazania)

Nie nie jst singletonem ale co mu mam przekazywac.

EDIT2:

Zaraz zaczne kodzic juz wiem o co biega z tymi lancuchami akcji zaimplementuje to na tym samym przykladziei pokaze thx.

Wykombinowalem cos takiego:
  1. public function Forward($ctrl, $actions = array('Index')) {
  2.  
  3. if(file_exists(DIR_PLUGINS_CTRL.$ctrl.'.php')) {
  4.  
  5. require_once(DIR_PLUGINS_CTRL.$ctrl.'.php');
  6.  
  7. }
  8.  
  9. else if(file_exists(DIR_COMPONENTS_CTRL.$ctrl.'.php')) {
  10.  
  11. require_once(DIR_COMPONENTS_CTRL.$ctrl.'.php');
  12.  
  13. }
  14.  
  15. if(class_exists($ctrl)) {
  16.  
  17. $forwardObj = new $ctrl();
  18.  
  19. switch(count($actions)) {
  20.  
  21. case 1:
  22. return (method_exists($forwardObj, $actions[0])) ? $htmlChainAction = $forwardObj -> $actions[0]() : $forwardObj -> Index();
  23. break;
  24.  
  25. case 2:
  26. if(method_exists($forwardObj, $actions[0]) && method_exists($forwardObj, $actions[1])) {
  27.  
  28. $forwardObj -> $actions[0]();
  29. return $forwardObj -> $actions[1]();
  30.  
  31. }
  32.  
  33. else {
  34.  
  35. return $forwardObj -> Index();
  36.  
  37. }
  38.  
  39. break;
  40.  
  41. case 3:
  42. if(method_exists($forwardObj, $actions[0]) && method_exists($forwardObj, $actions[1]) && method_exists($forwardObj, $actions[2])) {
  43.  
  44. $forwardObj -> $actions[0];
  45. $forwardObj -> $actions[1];
  46. return $forwardObj -> $actions[2];
  47.  
  48. }
  49.  
  50. else {
  51.  
  52. return $forwardObj -> Index();
  53.  
  54. }
  55.  
  56. break;
  57.  
  58.  
  59. }
  60.  
  61. }
  62.  
  63. return false;
  64.  
  65. }

Jak narazie mozna wykonac 3 akcje i tylko ostatnia zwraca nam wynik w postaci html.

Zrobilem to tak bo mi jest wygodnie, choc nie jest to napewno w 100% forward() ktore wy znacie z symfony czy zf(choc jest bardziej podobne do tego z zf).
Ogolnie rzecz biorac taka implementacja forward() moze sie przydac gdy chcemy wywolac kilka akcji pod rzad bez przeladowania strony i tylko ostatnia akcja zwraca nam wynik w postaci html(w moim przypadku).
Moze zdac egzanim gdy usuwamy news'a i chcemy na nowo wyswietlic wszystkie bez przeladowania strony robimy to za pomoca forward() lub ten sam efekt mozna uzyskac za pomoca redirect() z przeladowaniem strony.

Ogolnie ta implementacje co podalem wyzej to troche rozbuduje raczje ale wczesniejsza funckja forward() tez zostanie zmienie jej nazwe bo przy jednej funkcji sie zda bardziej niz te nowe forward();
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.