Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Wywoływanie route collection w wywołanej metodzie kontrolera
emillo91
post 7.08.2018, 21:52:46
Post #1





Grupa: Zarejestrowani
Postów: 92
Pomógł: 7
Dołączył: 29.03.2012

Ostrzeżenie: (0%)
-----


Witam. Tworzę mechanizm routingu, który ma za zadanie wywołać metodę klasy kontrolera w przypadku, gdy Router znajdzie w niej dopasowanie do ścieżki url w żądaniu GET. Wygląda to tak, że każda z metod klasy kontrolera musi zwracać tablicę, w której zawarta jest również ścieżka potrzebna do wywołania tej metody. Wszystko działa lecz problem powstaje w momencie, gdy w wywołanej metodzie kontrolera utworzę ponownie obiekt RouteCollection i wywołam metodę getallroutes() z klasy RouteCollection, z której również korzysta klasa Routera. Wtedy powstaje nieskończona pętla i na końcu wyskakuje komunikat: "Allowed memory size of 134217728 bytes exhausted (tried to allocate 262144 bytes)". Problem tkwi w metodzie getallroutes, która aby pobrać wszystkie ścieżki routingu musi pobrać informacje z metod wszystkich kontrolerów i dodać je do tworzonej tablicy routingu.
Poniżej wrzucam pliki klasy Router, Routecollection i przykłądowego kontrolera:

Router.php
  1. <?php
  2.  
  3. require 'usingclasses/RouteCollection.php';
  4. require 'controller.php';
  5. require 'usingclasses/RenderRouteView.php';
  6.  
  7. class Router
  8. {
  9. private $urlpath;
  10. private $request;
  11. private $dir = 'scripts/controllers/';
  12. private $collection;
  13.  
  14. public function __construct($urlpath, array $request)
  15. {
  16. $this->urlpath = $urlpath;
  17. $this->request = $request;
  18. $this->collection = new RouteCollection();
  19. $this->collection = $this->collection->getallroutes(); //tablica routingu
  20. }
  21.  
  22. /**
  23.   * @return array
  24.   */
  25. private function parseurl()
  26. {
  27. $url = explode('/', $this->urlpath);
  28. $url = array_filter($url);
  29.  
  30. return $url;
  31. }
  32.  
  33.  
  34. /**
  35.   * creates Controller's and View's object matched to url path
  36.   *
  37.   * @return mixed|null
  38.   * @throws Exception
  39.   */
  40. public function findroutecontroller() //metoda inicjująca pracę routera
  41. {
  42.  
  43.  
  44. foreach($this->collection as $routepath => $routename) //przetwarzanie tablicy routingu
  45. {
  46. if($routepath == implode('/', $this->parseurl()))
  47. {
  48. $viewob = new RenderRouteView($this->collection[$routepath]['view'],$this->collection[$routepath]['args']); // mało istotne
  49.  
  50. return $viewob->renderview();
  51. }
  52. }
  53.  
  54.  
  55. }
  56. }


RouteCollection.php
  1. <?php
  2.  
  3. class RouteCollection
  4. {
  5. private $directory = 'scripts/controllers/';
  6. private $routecollection = [];
  7. private $array = [];
  8.  
  9. /**
  10.   * Odpowiada za tworzenie tablicy [ścieżka/routingu => nazwa_routy]
  11.   *
  12.   * @return array
  13.   * @throws Exception
  14.   */
  15. public function getallroutes()
  16. {
  17.  
  18. foreach ($this->getdirfiles($this->directory) as $dirfile)
  19. {
  20. $ob = $this->createobjectfromdirfile($dirfile); // Tworzy dynamicznie obiekt kontrolera który chyba nie jest usuwany
  21.  
  22. if(is_object($ob)) {
  23. $obmethods = $this->getobjectmethods($ob);
  24. foreach ($obmethods as $method) { // pętla z metodami aktualnie przetwarzanego kontrolera
  25. if(!$this->getrepeatemethoddata($this->array, $ob->$method())) {
  26.  
  27. $this->array[$ob->$method()['route']] = $ob->$method(); // tworzenie tablicy [ścieżka/routingu => nazwa_routy]
  28. }
  29. }
  30. unset($obmethods);
  31. unset($ob);
  32.  
  33. }
  34. }
  35.  
  36. return $this->array;
  37. }
  38.  
  39. private function getdirfiles($dir)
  40. {
  41. return scandir($this->directory);
  42. }
  43.  
  44. private function createobjectfromdirfile($file)
  45. {
  46. if(is_file($this->directory.$file)) {
  47. $cutfilename = explode('.php', $file);
  48.  
  49. require_once $this->directory.$file;
  50.  
  51. $ob = new $cutfilename[0]();
  52.  
  53. return $ob;
  54. }
  55.  
  56. return null;
  57. }
  58.  
  59. private function getobjectmethods($object)
  60. {
  61. $arr = [];
  62. if(is_object($object))
  63. {
  64. $arr = get_class_methods($object);
  65. return $arr;
  66. }
  67.  
  68. return $arr;
  69. }
  70.  
  71. private function getrepeatemethoddata(array $array, $method)
  72. {
  73. if(!key_exists($method['route'], $array))
  74. {
  75. }
  76. if(key_exists($method['route'], $array))
  77. {
  78. throw new Exception('repeated keys');
  79. }
  80. if(in_array($method['routename'], array_values($array)) == false)
  81. {
  82. }
  83. if(in_array($method['routename'], array_values($array)) == true)
  84. {
  85. throw new Exception('repeated values');
  86. }
  87.  
  88. return false;
  89. }
  90. }


examplecontroller.php
  1. <?php
  2. require 'scripts/usingclasses/CreateForm.php';
  3.  
  4. class examplecontroller extends Controller
  5. {
  6.  
  7.  
  8. /**
  9.   * @return array
  10.   * @throws Exception
  11.   */
  12. public function someactionother()
  13. {
  14.  
  15. $createform = new CreateForm();
  16.  
  17. $cos = $this->getcollection();
  18. $form = $createform
  19. ->addformfield('input', 'login', 'Podaj login')
  20. ->addformfield('input', 'haslo', 'Podaj hasło')
  21. ->addformfield('submit', 'zapisz')
  22. ->renderform();
  23.  
  24. return $this->generaterouteargs('ma', 'jakas_routa', 'a.php', ['form'=> 'aa']);
  25. }
  26.  
  27.  
  28. private function getcollection()
  29. {
  30. $arr = [];
  31. $dane = new RouteCollection();
  32. $d = $dane->getallroutes();
  33.  
  34.  
  35. return $d;
  36. }
  37. }


Wszystko wywołuję w pliku index.php:

index.php
  1. <?php
  2. require 'scripts/Router.php';
  3. $path = !empty($_GET['path'])? $_GET['path']: null;
  4. $router = new Router($path, $_REQUEST);
  5.  
  6. $router->findroutecontroller();
  7.  


Wydaje mi się, że problem tkwi przy dynamicznym tworzeniu objektów kontrolera w 20 linii pliku RouteCollection.php czyli:
  1. $ob = $this->createobjectfromdirfile($dirfile);


Niestety aby pobrać informacje o metodach kontrolera w postaci tablicy to muszę najpierw utworzyć obiekt klasy kontrolera ale on chyba nie jest później niszczony przy kolejnym przebiegu pętli.

Edit:

Rozwiązałem mój problem. Cały problem tkwił w momencie tworzenia tablicy w której przywoływałem wszystkie metody dla utworzonego obiektu co najwidoczniej pochłaniało sporo pamięci. Rozwiązanie wygląda tak:
  1. public function getallroutes()
  2. {
  3. $arr =[];
  4. foreach ($this->getdirfiles($this->directory) as $file) {
  5. if(is_object($this->createobjectfromdirfile($file))) {
  6. $arr[get_class($this->createobjectfromdirfile($file))] = [
  7. 'class' => $this->createobjectfromdirfile($file),
  8. 'methods' => $this->getobjectmethods($this->createobjectfromdirfile($file))
  9. ];
  10. }
  11. }
  12. return $arr;
  13. }

Zamiast wywoływać metody to utworzyłem tablicę z obiektem klasy kontrolera pod kluczem 'class' oraz tablicą metod pod kluczem 'methods'. Wszystko wywołałem dopiero w klasie Router w taki sposób:
  1. foreach($this->collection as $iterate => $data) {
  2. $ob = $this->collection[$iterate];
  3.  
  4. foreach ($ob['methods'] as $method) {
  5. $classmethod = $ob['class']->$method();
  6. if ($classmethod['route'] == implode('/', $this->parseurl())) {
  7. $view = new RenderRouteView($classmethod['view'], $classmethod['args']);
  8.  
  9. return $view->renderview();
  10. }
  11. }
  12. }


Utworzyłem zmienną $ob w celu przywołania kolekcji dla danej iteracji. Później wywołałem tablicę array i z metodami dla danej iteracji i następnie wywoływałem metody w drugiej pętli. Nie wiem tylko czy jeśli będzie bardzo dużo metod do przejrzenia w danym kontrolerze (bo żeby porównać ścieżkę z metody ze ścieżką ze zmiennej get, muszę wywoływać kolejne metody kontrolera) to czy znowu nie zabraknie pamięci?

Ten post edytował emillo91 7.08.2018, 21:53:48
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 16.11.2018 - 17:38