Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Routing, url's i żądanie get
Forum PHP.pl > Forum > PHP
szubi95
Witam wszystkich!


Ostatnio zacząłem pisać mały routing. Napotkałem na dwa małe problemy(mianowicie związane z wysyłaniem parametrów getem), i nie wiem co z tym do końca zrobić. Wszystko jest oparte na path_info.


Przykładowo mam taki adres:

http://localhost/admin/users/show/5 ->path_info

W momencie wysłania formularza getem mam coś takiego:

http://localhost/admin/users/show/5/?param=4

I teraz choćby, jak temu zaradzić,a mianowicie, żeby żądanie wyglądało tak po wysłaniu formularza:

http://localhost/admin/users/show/5/4


Drugi problem:

Tak wyglądają tablice z danymi:



array(1) {
["param"]=>
string(1) "4"
}

array(4) {
[0]=>
string(5) "admin"
[1]=>
string(5) "users"
[2]=>
string(4) "show"
[3]=>
string(6) ":param"
}

array(4) {
["module"]=>
string(0) ""
["controller"]=>
string(5) "users"
["action"]=>
string(4) "show"
["params"]=>
array(1) {
[1]=>
string(1) "5"
}
}


Pierwsza to get, druga to path_info(a raczej zdefiniowany przeze mnie adres w tablicy $_routes), a trzecia to wyjściowa, która poleci do PageControllera. Nie wiem, czy mam połączyć path_info z takim getem, czy można jakoś inaczej to obejść. Wyszukiwanie odpowiednich adresów opiera się wyłącznie na tym co zawiera path_info(w momencie otrzymania jakiegoś parametru adres nadal będzie pasował, a według mnie nie powinien i dlatego myślę o połączeniu, żeby była sprawdzana całość a potem klasa Request i tak dostanie to co jej będzie potrzebne - żądanie).

Z drugiej strony w przypadku takiego połączenia i wyszukiwania adresów klucze geta nie będą mnie kompletnie interesowały(czyli wyciągam tylko wartości i resztę usuwam i to jest dla mnie trochę dziwne bo to oznacza w zasadzie, że klucze mogą być dowolne:

http://localhost/admin/users/show/5/?PARAM=4

Ewentualnie klucz ten będzie oznaczał klucz w tabeli definiowania trasy,a ta jedynka pierwszy index tablicy $_GET:


  1.  
  2. <?php
  3.  
  4. $router = new Router();
  5.  
  6. $router->add(
  7. '/admin/users/show/:param',
  8. 'controller' => 'users',
  9. 'action' => 'show',
  10. [b]'PARAM' => 1[/b]
  11. )
  12. );
  13.  


Ma ktoś może jakiś pomysł?


Pozdrawiam,
szubi
Pyton_000
Zerknij w dokumentację CakePHP 2.x bo widzę tu bardzo duże podobieństwo (chyba że nim się wzorowałeś smile.gif )
szubi95
W porządku Pyton smile.gif Jutro zerknę, bo dzisiaj już nie mam siły :/ Wrzucam dwie klasy, żeby widać było jak to mniej więcej wygląda(jakby mógł ktoś też powiedzieć czy idę w dobrą stronę, czy też złą byłbym wdzięczny):

  1. <?php
  2.  
  3. namespace Router;
  4.  
  5.  
  6. use Router\Components\Request;
  7. use Router\IAbstract\AbstractRouter;
  8. use Router\Components\Url;
  9.  
  10.  
  11. class Router extends AbstractRouter
  12. {
  13. protected $routes = [];
  14.  
  15. protected $module;
  16. protected $controller;
  17. protected $action;
  18. protected $params = [];
  19.  
  20. protected $regex = [
  21. ':module' => '#(^[\a-zA-Z]*)$#',
  22. ':controller' => '#(^[a-zA-Z]*)$#',
  23. ':action' => '#(^[-a-zA-Z]*)$#',
  24. ':name' => '#(^[-a-zA-Z]*)$#',
  25. ':param' => '#(^[0-9]*)$#'
  26. ];
  27.  
  28. protected $regex_keys = [];
  29.  
  30. private $default_module;
  31. private $default_controller;
  32. private $default_action;
  33.  
  34. protected $request;
  35.  
  36. public function __construct()
  37. {
  38. $this->module = '';
  39. $this->default_module = '';
  40. $this->default_controller = '';
  41. $this->default_action = '';
  42.  
  43. $this->setRequest(new Request());
  44. $this->setRegexKeys();
  45. }
  46.  
  47. public function add($path, Array $route)
  48. {
  49. $combine[] = $path;
  50. $combine[] = $route;
  51. $this->routes[] = $combine;
  52. return $this;
  53. }
  54.  
  55. public function remove(Array $route)
  56. {
  57. foreach ($this->routes as $i => $stored) {
  58. if ($stored == $route) {
  59. unset($this->routes[$i]);
  60. }
  61. }
  62. }
  63.  
  64. public function resolve()
  65. {
  66. $path_info = $this->routeArray(new Url());
  67.  
  68. // i tutaj właśnie to prawdopodobne łączenia z getem, albo osobna funkcja
  69.  
  70. //var_dump($_GET);
  71.  
  72. //$path_info = array();
  73.  
  74. //var_dump($path_info);
  75.  
  76.  
  77. /*if (empty($path_info)) {
  78.   echo 'cos2';
  79.  
  80.   $path = key($_GET);
  81.   $path_info = explode('/', trim($path, '/'));
  82.   //$path_info = array_values($_GET);
  83.   //unset($_GET);
  84.  
  85.   //var_dump($_GET);
  86.   var_dump($path_info);
  87.   }*/
  88.  
  89.  
  90.  
  91. foreach ($this->routes as $element) {
  92.  
  93. $address = explode('/', trim($element[0], '/'));
  94. $values = array_values($element[1]);
  95.  
  96. if (true === $this->searchAddress($address, $path_info)) {
  97.  
  98. var_dump($address);
  99.  
  100. $this->setElementIfExist('module', $address, $element[1], $path_info);
  101. $check_controller = $this->setElementIfExist('controller', $address, $element[1], $path_info);
  102. $check_action = $this->setElementIfExist('action', $address, $element[1], $path_info);
  103.  
  104. if ($check_controller && $check_action) {
  105.  
  106. $this->setParams($path_info, $values, $address);
  107.  
  108. $action_array['module'] = $this->module;
  109. $action_array['controller'] = $this->controller;
  110. $action_array['action'] = $this->action;
  111. $action_array['params'] = $this->params;
  112.  
  113. var_dump($action_array);
  114.  
  115. return true;
  116. } else {
  117.  
  118. empty($this->module) ? $action_array['module'] = $this->default_module : $action_array['module'] = $this->module;
  119.  
  120. $action_array['controller'] = $this->default_controller;
  121. $action_array['action'] = $this->default_action;
  122.  
  123. var_dump($action_array);
  124.  
  125. }
  126. }
  127. }
  128.  
  129. return false;
  130. }
  131.  
  132. private function setParams($path_info, $values, $address)
  133. {
  134. $index = 1;
  135. for ($i=0; $i<count($path_info); $i++) {
  136.  
  137. if (preg_match("#(^[:{1}][a-zA-Z]+)#", $address[$i]) && $path_info[$i] != $this->controller && $path_info[$i] != $this->action && $path_info[$i] != $this->module) {
  138. $this->params[$index] = $path_info[$i];
  139. $index++;
  140. } else {
  141. if ($address[$i] == $path_info[$i] && $address[$i] != $this->controller && $address[$i] != $this->action && $path_info[$i] != $this->module) {
  142. foreach ($values as $value) {
  143.  
  144. if ($value == $path_info[$i]) {
  145. $this->params[$index] = $path_info[$i];
  146. $index++;
  147. }
  148. }
  149. }
  150. }
  151. }
  152. }
  153.  
  154. public function setDefaultModule($namespace)
  155. {
  156. $this->default_module = $this->stringFilter($namespace);
  157. }
  158.  
  159. public function setDefaultController($controller)
  160. {
  161. $this->default_controller = $this->stringFilter($controller);
  162. }
  163.  
  164. public function setDefaultAction($action)
  165. {
  166. $this->default_action = $this->stringFilter($action);
  167. }
  168.  
  169. protected function setRequest(Request $request)
  170. {
  171. $this->request = $request;
  172. }
  173.  
  174. public function request($type, $action=null)
  175. {
  176. $this->request->parse($type, $action);
  177. }
  178. }
  179.  


i druga klasa Abstract:

  1.  
  2. <?php
  3.  
  4. namespace Router\IAbstract;
  5.  
  6.  
  7. use Router\Components\Url;
  8.  
  9.  
  10. abstract class AbstractRouter implements IRouter
  11. {
  12. protected $routes = [];
  13.  
  14. protected $module;
  15. protected $controller;
  16. protected $action;
  17. protected $params = [];
  18.  
  19. protected $regex = [];
  20.  
  21. protected $regex_keys = [];
  22.  
  23. protected $index;
  24.  
  25. protected function setRegexKeys()
  26. {
  27. $this->regex_keys = array_keys($this->regex);
  28. }
  29.  
  30. protected function searchAddress(Array $routes, Array $path_info)
  31. {
  32. // parse to GET
  33.  
  34. for ($i = 0; $i < count($path_info); $i++) {
  35.  
  36. if (!isset($routes[$i]) || count($routes) > count($path_info)) {
  37. return false;
  38. }
  39.  
  40. if (preg_match("#(^[:]{1}[a-zA-Z])#", $routes[$i])) {
  41.  
  42. $is_exist = false;
  43. foreach ($this->regex_keys as $key) {
  44. if ($key == $routes[$i]) {
  45. if (preg_match($this->regex[$key], $path_info[$i])) { // klucze nienumeryczne!!
  46. $is_exist = true;
  47. break;
  48. }
  49. }
  50. }
  51.  
  52. if (false === $is_exist) {
  53. return false;
  54. }
  55. } else {
  56.  
  57. if (isset($path_info[$i])) {
  58. if ($path_info[$i] == $routes[$i]) {
  59.  
  60. if ($i == count($path_info)) {
  61. if (count($path_info) < count($routes)) {
  62. return false;
  63. }
  64. }
  65. } else {
  66. return false;
  67. }
  68. }
  69. }
  70. }
  71.  
  72. return true;
  73. }
  74.  
  75. protected function setElementIfExist($name, Array $address, Array $element, Array $path_info)
  76. {
  77. foreach ($element as $key => $value) {
  78.  
  79. if (strtolower($name) == strtolower($key)) {
  80. for ($i=0; $i < count($path_info); $i++) {
  81.  
  82. if ($address[$i] == $value) {
  83. $this->$name = $address[$i];
  84. return true;
  85. } else {
  86. if (is_int($value)) {
  87. for ($j=0; $j < count($address); $j++) {
  88. if (preg_match('#(^[:]{1}[a-zA-Z])#', $address[$j])) {
  89. $addr= str_replace(':', '', $address[$j]);
  90.  
  91. if ($name == $addr) {
  92. ++$this->index;
  93.  
  94. if ($this->index == $value) {
  95. $this->$name = $path_info[$j];
  96. return true;
  97. }
  98. }
  99. }
  100. }
  101. }
  102. }
  103. }
  104. }
  105. }
  106.  
  107. return false;
  108. }
  109.  
  110. protected function stringFilter($string)
  111. {
  112. $string = filter_var($string, FILTER_SANITIZE_STRING);
  113. $string = filter_var($string, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
  114. return $string;
  115. }
  116.  
  117. public function routeArray(Url $url)
  118. {
  119. $url->divideAddress($url->getAddress());
  120. return $url->getActions();
  121. }
  122. }
  123.  
  124.  


Zaawansowane to myśle to to nie jest, ale na początek pisania myślę tragedii chyba nie ma wink.gif

Pozdrawiam,
szubi

Nie napisałem wcześniej: Nie wzoruję się na niczym w zasadzie. Zerknąłem do Cake'a i szczerze powiedziawszy zainteresował mnie ten fragmencik:

  1. Router::connect(
  2. "/:controller/:id",
  3. array("action" => "edit", "[method]" => "PUT"),
  4. array("id" => "[0-9]+")
  5. );


ale wolałbym chyba zrobić osobną klasę Request i w takiej mniej więcej formie to definiować:

  1. $router->add(
  2. '/admin/users/show/:param',
  3. 'controller' => 'users',
  4. 'action' => 'show',
  5. 'param' => 1
  6. )
  7. )->request('get');


A wracając do mojego pytania:

Połączyłem path_info z getem i w tej chwili to wygląda tak:

http://localhost/index/admin/users/show/?param=2 -> wysłane getem z formularza

http://localhost/index/admin/users/show/2 -> sam path_info

Jeśli get istnieje to zostaje dołączony do tablicy path_info razem ze swoim indeksem. Działa pod jednym warunkiem. Kiedy jego klucz jest taki sam jak klucz zdefiniowany w drugiej tablicy(akcji):


?param=2

  1. 'controller' => 'users',
  2. 'action' => 'show',
  3. 'PARAM' => 1
  4. )


Trochę ograniczenie, ale z drugiej strony normalnie też to tak raczej wygląda, bo przecież klucz nie powinien być bez znaczenia.
Teraz oba adresy zwracają dokładnie to samo, ale nie jestem do końca pewien tego rozwiązania. Czy mógłbym prosić o jakieś wskazówki?

Pozdrawiam,
szubi
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.