Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: DbM Framework - Autorska aplikacja frameworka opartego na wzorcu MVC
Forum PHP.pl > Inne > Oceny
Stron: 1, 2
nospor
sorki, mialem na mysli kontrollery a nie model.

czyli nie
IndexController

public function __construct(Database $database)
{
$model = new BlogModel($database);
$this->model = $model;

$translation = new Translation();
$this->translation = $translation;
}

a
IndexController

public function __construct(Database $database)
{
parent::__construct($database);
$model = new BlogModel($database);
$this->model = $model;

$translation = new Translation();
$this->translation = $translation;
}
Malinaa
Aha, czyli dodać tylko linijkę:
parent::__construct($database);
w konstruktorze, ponieważ dziedziczy z kontrolera bazowego,
no i już wiem jak nazwać kontroler bazowy
AbstractController to BaseController
no i wszystko jasne smile.gif

Kod
Moze to i glupio wyglada ale tak sie robi. W sensie nie robi sie tak jak ty to robisz, tylko sie uzywa automatow co juz ci proponowano. Ale tak wlasnie generalnie wyglada DI. Obiekt jest tworzony raz a potem przekazywany wszedzie tam gdzie potrzeba. Ulatwi to wiele spraw, chocby testowanie aplikacji


A to nawet nie jest bez sensu zrobić takie ćwiczenie wink.gif

Ok, po zmianie został jeszcze routing, takie sobie linki SEO friendly wymyśliłem, np.:
/praesent-euismod-gravida-libero-a-luctus-nisi-fermentum-nec,art,5.html
że nie ma lekko z tym routingiem.

Mniejsza z tym routingiem, czy jest tu jakieś miejsce gdzie przydałby się np. AbstractController, albo Interfejs, a może Fabryczka ?; )
nospor
Cytat
Ok, po zmianie został jeszcze routing, takie sobie linki SEO friendly wymyśliłem, np.:
/praesent-euismod-gravida-libero-a-luctus-nisi-fermentum-nec,art,5.html
że nie ma lekko z tym routingiem.

No ale jakies pytanie w zwiazku z tym czy tylko komunikujesz? wink.gif

Cytat
Mniejsza z tym routingiem, czy jest tu jakieś miejsce gdzie przydałby się np. AbstractController, albo Interfejs, a może Fabryczka ?; )

No interfejsy daje sie w zasadzie wszedzie. u ciebie napewno na wszystko to co wstrzykujesz powinny byc interfejsy
com
Cytat(Tomplus @ 24.01.2024, 09:31:42 ) *
Ja osobiście rozumiem dlaczego ktoś tworzy i stosuje własne FW. Mają kilka zalet:
- na początku są proste w obsłudze
- są lekkie
- uwzględniają specyfikę hostingu
- są szyte na miarę umiejętności twórcy.

Jednak problemy przychodzą gdy, projekt się rozrasta i różnych powiązań modułów jest coraz więcej. Zaczynają pojawiać się zbędne powtórzenia, blędy tam gdzie nie powinno ich być.


No i to jest pierwszy i podstawowy błąd, kiedyś kiedy środowisko PHP raczkowało powstawało wiele potworków, która były systemami Legancy już na samym starcie projektu, potem projekt coraz bardziej się rozrastał i zainwestowanych środków nikt już nikomu nie zwróci, wiec utrzymuje się takie twory po dziś, ale w 2024 roku powinno nie być już zrozumienia dla takich praktyk. Sam tak jak pisałem wyżej wiele lat temu tworzyłem własne bo mi się jak każdemu wydawało że prosty projekt to poco zatrudniać taka kobyle jak pełnoprawny FW, ale czasy mamy inne i FW też pozwalają na to by dla mikroporjektów odpalać je i nie jest to taki już ogromny narzut jak kiedyś, dlatego uśmiercono już Silexa czy Lumena, bo Symfony czy Laravel potrafią je w pełni zastąpić. A największym problemem tego było to co napisałeś: "są szyte na miarę umiejętności twórcy.", w zeszył roku przez pewien czas przyszło mi pracować z takim systemem, jego poziom rozwoju zatrzymał się na PHP 5.4, a na starcie wszystkie błędy musiały być tam filtrowane bo było ponad 500 błędów o tym, że używana jest metoda klasy jako statyczna metoda, nie było szans na podbicie nawet do 5.5, bez przepisania połowy tego kodu, pomijając to że jest tak napisany ze nawet rector by sobie z tym nie poradził, w planach miało być przejście na PHP 5.6 a potem 7, ale jak wiadomo nowe funkcjonalności wygrały z naprawa tego co przez lata tam napsuto. Dlatego nie róbmy sobie krzywdy tworząc takie fw dla ideii, jeśli chcemy poznać jak coś działa to kod jest open source można przejrzeć źródła i testy i nawet jak nadal uparcie chcemy coś pisać to trzeba już mieć doświadczenie tka jak ktoś już tutaj wcześniej o tym wspominał.

Cytat
Malinaa musisz sobie postawić zasadnicze pytanie poco to tworzysz?


Cytat(Malinaa @ 18.01.2024, 21:38:13 ) *
Pan Bóg stworzył istotę dla hecy, z tyłu plecy, z przodu plecy. A jednak po niej przyszedł ten, który był zrodzony, a nie stworzony smile.gif
Chcesz pomóc? Napisz jak mam zakodować DI i inne drobiazgi, o których pisałem wyżej.


Chcę pomoc ale kompletnie nie zrozumiałeś przekazu, wysłałem Ci wartościowy materiał https://symfony.com/doc/current/create_framework/index.html do którego nie zajrzałeś nawet. Uparłeś się żeby stworzyć FW bez composera, co w 2024 jest już niedopuszczalne w żadnym greenfield`zie. Kiedy w końcu PHP dojrzało do pewnych standardów które w Javie, czy C# mamy od lat i za których brak PHP przez lata był hejtowany, ty robisz wszytko by nadal powielać wszystkie złe praktyki jakie przez lata w tym języku stosowano. Wysiałem tobie również https://phptherightway.com/ tutaj również nie zajrzałeś, tam masz odpowiedzi chociażby na pytanie jak wdrożyć DI https://phptherightway.com/#dependency_injection Skoro chcesz poznać jak to działa to o tym poczytaj, nie oczekuj że podam Ci coś na tacy bo wtedy nie poznasz jak to działa, ale jak chcesz naprawdę czegoś się nauczyć z tworzenia tego FW to zanim zaczniesz pisać kod musisz zglebić te zagadnienia i przed wszystkim słuchać rad innych, którzy też kiedyś to poznawali tak jak Ty, nikt się nie budzi z tą wiedzą, zobacz przez ile postów z nospor pisałeś o tym jak wdrożyć DI, a wynikało to z tego że nie wiedziałeś czym jest ten wzorzec, wiec tego nie potrafiłeś przełożyć na kod. Jeśli chcesz naprawdę do czegoś w tym FW dojść to musisz bardzo dużo poczytać o tym, a dopiero potem próbować to przełożyć na kod, my siadamy do kodu bo już znamy pojecie DI itp, ty je poznajesz wiec to normalne że nie widzisz tego jeszcze w kodzie, ale jakbyś miał już teorie za sobą to byś to tak samo widział jak my smile.gif Patrzysz na to że Wordpress nie ma composera, co oczywiście jest prawdą ale on powstał w 2004 roku, tam ten kod jest tak stary że jak powstawał było jeszcze PHP 4.X, potem 5.0, stąd ma wiele rzeczy których by w 2024 roku nie zastosowano, zaczynając od konwencji nazewnictwa klas i metod, braku composera w oficjalnym core i wsparcia dla PSR, ale ten kod ma 20 lat, nikt czegoś co przez 20 lat szczególnie w ramach open source nie przepisze na obecne standardy, będzie to utrzymywane w tej formie do końca jego istnienia, ale przez to własnie PHP jest tak bardzo nienawidzony, za Wordpressa bo nadal ludzie myślą że PHP wygląda tak jak Wordpress, ale jak ten system blogowy zasila jakieś 60% internetu to nie ma możliwości tak drastycznych zmian, bo tam musi być zachowana kompatybilność by 60% internetu się nie wysypało, ale to nie znaczy, że jesteśmy zmuszeni do tego by dalej tak pisać w Wordpressie, bo nie jesteśmy możemy użyć https://roots.io/bedrock/ i mieć kod na miarę 2024 roku i musisz to kolego zrozumieć, że nie jesteśmy już w 2004 roku, nie ma miejsca na tworzenie tego w ten sposób jeśli faktycznie chcesz się czegoś nauczyć i kiedyś nam za to podziękujesz że nie szedłeś tą ślepą drogą smile.gif Jak zaczniesz pisać to tak jak na 2024 rok przystało wtedy bardzo chętnie zrobię Ci Review kodu smile.gif Swoją drogą już Ci pisałem MVC to tylko pewna konwencja(https://www.youtube.com/watch?v=pJSoS4VBIW4&themeRefresh=1 poza tym obejrzyj sobie to), nie da się jej zaadaptować do WEB, to zawsze będzie jakaś wariacja wokół tego i nie ma problemu by katalog z templatkami nazywał się templates, a jak robisz templatki w czystym PHP/HTML to jak najbardziej dobrym rozszerzeniem dla tego jest phtml, to już taki standard(wprawdzie już raczej się nie używa tylko systemów jak twig ale w teorii można)

  1. Fatal error: Uncaught TypeError: Argument 1 passed to Dbm\Classes\Router::matchRoute() must be of the type string, null given, called in \www\dbm\application\classes\Router.php on line 38 and defined in \www\dbm\application\classes\Router.php:83 Stack trace: #0 \www\dbm\application\classes\Router.php(38): Dbm\Classes\Router->matchRoute(NULL) #1 \www\dbm\application\routes.php(43): Dbm\Classes\Router->dispatch(NULL) #2 \www\dbm\public\index.php(54): {closure}(Object(Dbm\Classes\Database)) #3 {main} thrown in \www\dbm\application\classes\Router.php on line 83


Swoją droga nie można tego nawet uruchomić bo na sztywno zaszyłeś w metodzie dispatch w 37 lini klasy Router
  1. $uri = $this->matchLocalhost($uri);

i nie można było tego odpalić na jakiś vhoscie, to powinno być opcjonalne albo konfigurowalne. Fajne logo takie trochę kradzione od JetBrains wink.gif

Cytat(Malinaa @ 6.02.2024, 18:50:18 ) *
Ok, po zmianie został jeszcze routing, takie sobie linki SEO friendly wymyśliłem, np.:
/praesent-euismod-gravida-libero-a-luctus-nisi-fermentum-nec,art,5.html
że nie ma lekko z tym routingiem.

To nie jest akurat SEO friendly https://www.seroundtable.com/google-commas-...tion-32741.html smile.gif

Prosze tutaj obsługa routingu(żeby nie było że nie chcę pomoc)
Klasa Router
  1.  
  2. class Router
  3. {
  4. protected $routes = [];
  5. private $database;
  6.  
  7. public function __construct(Database $database)
  8. {
  9. $this->database = $database;
  10. }
  11.  
  12. public function addRoute(string $route, array $arrayController): void
  13. {
  14. $arrayControllerAction = $this->changeArrayKey($arrayController, ['controller', 'method']);
  15. $this->routes[$route] = $arrayControllerAction;
  16. }
  17.  
  18. public function dispatch(string $uri): void
  19. {
  20. $database = $this->database;
  21.  
  22. $uri = $this->matchLocalhost($uri);
  23. $route = $this->matchRoute($uri);
  24. $uri = $route['uri'];
  25.  
  26. $hasParams = false;
  27. if (!empty($route['params'])) {
  28. $hasParams = true;
  29. $uri = $this->buildRouteUri($route['paths'], $route['params']);
  30. }
  31.  
  32. if (array_key_exists($uri, $this->routes)) {
  33. $controller = $this->routes[$uri]['controller'];
  34. $method = $this->routes[$uri]['method'];
  35.  
  36. if (class_exists($controller)) {
  37. $controllerInstance = new $controller($database);
  38.  
  39. if (method_exists($controllerInstance, $method)) {
  40. if ($hasParams) {
  41. $controllerInstance->$method((int)end($route['params']));
  42. } else {
  43. $controllerInstance->$method();
  44. }
  45.  
  46. } else {
  47. throw new ExceptionHandler("No method $method on class $controller!", 500);
  48. }
  49. } else {
  50. throw new ExceptionHandler("No controller $controller!", 500);
  51. }
  52. } else {
  53. throw new ExceptionHandler("Route not found! addRoute('$uri')", 404);
  54. }
  55. }
  56.  
  57. private function changeArrayKey(array $array, array $keys): array
  58. {
  59. foreach ($array as $key => $value) {
  60. $newArray[$keys[$key]] = $value;
  61. }
  62.  
  63. return $newArray;
  64. }
  65.  
  66. private function matchLocalhost(string $uri): ?string
  67. {
  68. $haystack = APP_PATH;
  69. $needle = 'localhost';
  70.  
  71. if (strpos($haystack, $needle) !== false) {
  72. $folder = substr($haystack, strpos($haystack, $needle) + strlen($needle));
  73.  
  74. return str_replace($folder, '/', $uri);
  75. }
  76.  
  77. return null;
  78. }
  79.  
  80. private function buildRouteUri(array $paths, array $params): string
  81. {
  82. $params[0] = '{#}';
  83. $params[count($params) - 1] = '{id}';
  84. return '/'.implode('/', $paths). '/'. implode(',', $params).'.html';
  85. }
  86.  
  87. private function matchRoute(string $uri): array
  88. {
  89. $path = filter_var($uri, FILTER_SANITIZE_URL);
  90. $path = ltrim($path, '/');
  91. $path = explode("/", $path);
  92.  
  93. if (($pos = strpos($uri, '?')) !== false) {
  94. $uri = substr($uri, 0, $pos);
  95. }
  96. $paths = [];
  97. $params = [];
  98. foreach ($path as $subPath) {
  99. if (strpos($subPath, '.html') !== false) {
  100. $params = explode(',', $subPath);
  101. $param = end($params);
  102. if (($pos = strpos($param, '.html')) !== false) {
  103. $params[count($params) - 1] = substr($param, 0, $pos);
  104. }
  105. } else {
  106. $paths[] = $subPath;
  107. }
  108.  
  109. }
  110.  
  111. /*if (strpos($uri, ',') !== false) {
  112.   $uri = substr($uri, 0, 1) . substr($uri, strpos($uri, ',') + 1);
  113.   }*/
  114.  
  115. /* $parts = explode(',', $uri);
  116.   $uri = '/' . array_pop($parts); */
  117.  
  118. foreach($path as $index => $param){
  119. if(preg_match("/{.*}/", $param)){
  120. $indexNum[] = $index;
  121. }
  122. }
  123.  
  124. //print_r($indexNum);
  125.  
  126. /*if ((strpos($uri, '-')) !== false) {
  127.   //$parts = explode('/', $uri);
  128.   //$last = array_pop($parts);
  129.   //echo ' | '. $last;
  130.  
  131.   $link = str_replace(['/', '.html'], '', $uri);
  132.   $segments = explode(',', str_replace('/', '', $link));
  133.  
  134.   foreach ($segments as $key => $value) {
  135.   if (is_numeric($value)) {
  136.   $segments[$key] = '{$}';
  137.   }
  138.   if ((strpos($value, '-')) !== false) {
  139.   $segments[$key] = '{#}';
  140.   }
  141.   }
  142.  
  143.   //$uri = '/' . $path[0] . '/' . implode(',', $segments) . '.html';
  144.   $uri = '/' . implode(',', $segments) . '.html';
  145.  
  146.   //echo $uri;
  147.   }*/
  148.  
  149. return [
  150. 'uri' => $uri,
  151. 'paths' => $paths,
  152. 'params' => $params
  153. ];
  154. }
  155.  
  156. /* private function requestMethod() : string
  157.   {
  158.   return $_SERVER['REQUEST_METHOD'];
  159.   }
  160.  
  161.   private function requestPath(): string
  162.   {
  163.   return parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
  164.   } */
  165. }
  166.  


Plik routes.php

  1. return function (Database $database) {
  2. $uri = $_SERVER['REQUEST_URI'];
  3.  
  4. $router = new Router($database);
  5.  
  6. $router->addRoute('/', [IndexController::class, 'index']);
  7. $router->addRoute('/link.html', [IndexController::class, 'linkMethod']);
  8. $router->addRoute('/home.html', [HomeController::class, 'index']);
  9. $router->addRoute('/about.html', [AboutController::class, 'index']);
  10. $router->addRoute('/contact.html', [ContactController::class, 'index']);
  11. $router->addRoute('/regulation.html', [RegulationController::class, 'index']);
  12. $router->addRoute('/page', [PageController::class, 'index']);
  13. $router->addRoute('/page/site', [PageController::class, 'siteMethod']); // ? /page/site.html
  14. $router->addRoute('/site.html', [PageController::class, 'siteMethod']); // ?
  15. $router->addRoute('/offer.html', [PageController::class, 'offerMethod']); // /{#},offer.html
  16. $router->addRoute('/blog', [BlogController::class, 'index']);
  17. $router->addRoute('/blog/sections', [BlogController::class, 'sectionsMethod']);
  18. $router->addRoute('/blog/{#},sec,{id}.html', [BlogController::class, 'sectionMethod']);
  19. $router->addRoute('/blog/{#},art,{id}.html', [BlogController::class, 'articleMethod']);
  20.  
  21. $router->dispatch($uri);
  22. };



W pliku routes musiałem poprawić route dla artykułow bo pattern się nie zgadzał z regułami rewrite oraz linkami na stronie

  1. private function buildRouteUri(array $paths, array $params): string
  2. {
  3. $params[0] = '{#}';
  4. if (is_numeric($params[count($params) - 1])) {
  5. $params[count($params) - 1] = '{id}';
  6. }
  7. if (!empty($paths)) {
  8. $paths = '/'.implode('/', $paths). '/';
  9. } else {
  10. $paths = '/';
  11. }
  12. return $paths . implode(',', $params).'.html';
  13. }


Mała zamiana do obsługi stron typu the-best-offer,offer.html

  1. private function matchRoute(string $uri): array
  2. {
  3. $path = filter_var($uri, FILTER_SANITIZE_URL);
  4. $path = ltrim($path, '/');
  5. $path = explode("/", $path);
  6.  
  7. if (($pos = strpos($uri, '?')) !== false) {
  8. $uri = substr($uri, 0, $pos);
  9. }
  10. $paths = [];
  11. $params = [];
  12. foreach ($path as $subPath) {
  13. if (strpos($subPath, '.html') !== false) {
  14. $params = explode(',', $subPath);
  15. if (end($params) === $subPath) {
  16. $params = [];
  17. break;
  18. }
  19. $param = end($params);
  20. if (($pos = strpos($param, '.html')) !== false) {
  21. $params[count($params) - 1] = substr($param, 0, $pos);
  22. }
  23. } else {
  24. $paths[] = $subPath;
  25. }
  26.  
  27. }
  28.  
  29. /*if (strpos($uri, ',') !== false) {
  30.   $uri = substr($uri, 0, 1) . substr($uri, strpos($uri, ',') + 1);
  31.   }*/
  32.  
  33. /* $parts = explode(',', $uri);
  34.   $uri = '/' . array_pop($parts); */
  35.  
  36. foreach($path as $index => $param){
  37. if(preg_match("/{.*}/", $param)){
  38. $indexNum[] = $index;
  39. }
  40. }
  41.  
  42. //print_r($indexNum);
  43.  
  44. /*if ((strpos($uri, '-')) !== false) {
  45.   //$parts = explode('/', $uri);
  46.   //$last = array_pop($parts);
  47.   //echo ' | '. $last;
  48.  
  49.   $link = str_replace(['/', '.html'], '', $uri);
  50.   $segments = explode(',', str_replace('/', '', $link));
  51.  
  52.   foreach ($segments as $key => $value) {
  53.   if (is_numeric($value)) {
  54.   $segments[$key] = '{$}';
  55.   }
  56.   if ((strpos($value, '-')) !== false) {
  57.   $segments[$key] = '{#}';
  58.   }
  59.   }
  60.  
  61.   //$uri = '/' . $path[0] . '/' . implode(',', $segments) . '.html';
  62.   $uri = '/' . implode(',', $segments) . '.html';
  63.  
  64.   //echo $uri;
  65.   }*/
  66.  
  67. return [
  68. 'uri' => $uri,
  69. 'paths' => $paths,
  70. 'params' => $params
  71. ];
  72. }


oraz matchRoute by nie łapało niepotrzebnie /link.html jako pattern /{#}.html wtedy kiedy nie powinno wink.gif

poza tym powinno być raczej
1,user.html
a nie user,1.html skoro już taka konwencje przyjąłeś w offer smile.gif

ale jak tak ma być jak masz to wtedy jeszcze taka zmiana
  1. private function buildRouteUri(array $paths, array $params): string
  2. {
  3. if (count($params) > 2) {
  4. $params[0] = '{#}';
  5. }
  6. if (is_numeric($params[count($params) - 1])) {
  7. $params[count($params) - 1] = '{id}';
  8. }
  9. if (!empty($paths)) {
  10. $paths = '/'.implode('/', $paths). '/';
  11. } else {
  12. $paths = '/';
  13. }
  14. return $paths . implode(',', $params).'.html';
  15. }


i w routes.php

  1. return function (Database $database) {
  2. $uri = $_SERVER['REQUEST_URI'];
  3.  
  4. $router = new Router($database);
  5.  
  6. $router->addRoute('/', [IndexController::class, 'index']);
  7. $router->addRoute('/link.html', [IndexController::class, 'linkMethod']);
  8. $router->addRoute('/home.html', [HomeController::class, 'index']);
  9. $router->addRoute('/about.html', [AboutController::class, 'index']);
  10. $router->addRoute('/contact.html', [ContactController::class, 'index']);
  11. $router->addRoute('/regulation.html', [RegulationController::class, 'index']);
  12. $router->addRoute('/page', [PageController::class, 'index']);
  13. $router->addRoute('/page/site', [PageController::class, 'siteMethod']); // ? /page/site.html
  14. $router->addRoute('/site.html', [PageController::class, 'siteMethod']); // ?
  15. $router->addRoute('/offer.html', [PageController::class, 'offerMethod']); // /{#},offer.html
  16. $router->addRoute('/{#},offer.html', [PageController::class, 'offerMethod']); // /{#},offer.html
  17. $router->addRoute('/blog', [BlogController::class, 'index']);
  18. $router->addRoute('/blog/sections', [BlogController::class, 'sectionsMethod']);
  19. $router->addRoute('/blog/{#},sec,{id}.html', [BlogController::class, 'sectionMethod']);
  20. $router->addRoute('/blog/{#},art,{id}.html', [BlogController::class, 'articleMethod']);
  21. $router->addRoute('/{#},sec,{id}.html', [BlogController::class, 'sectionMethod']);
  22. $router->addRoute('/{#},art,{id}.html', [BlogController::class, 'articleMethod']);
  23. $router->addRoute('/user,{id}.html', [UserController::class, 'index']);
  24.  
  25. $router->dispatch($uri);
  26. };


Oczyścicie musisz poprawić UserController według nowej konwencji z DI

Popraw tez linki bo potem musisz mieć powielone reguły bo raz są z blog raz bez, zależy gdzie klikniesz:
  1. $router->addRoute('/blog/{#},sec,{id}.html', [BlogController::class, 'sectionMethod']);
  2. $router->addRoute('/blog/{#},art,{id}.html', [BlogController::class, 'articleMethod']);
  3. $router->addRoute('/{#},sec,{id}.html', [BlogController::class, 'sectionMethod']);
  4. $router->addRoute('/{#},art,{id}.html', [BlogController::class, 'articleMethod']);


Jeszcze małą zmiana by każdy pattern był obsługiwany
  1. private function buildRouteUri(array $paths, array $params): string
  2. {
  3. $paramsLength = count($params);
  4. if (!is_numeric($params[0]) && $paramsLength > 2) { // pattern /{#},sec,{id}.html itp
  5. $params[0] = '{#}';
  6. }
  7. if (!is_numeric($params[0]) && !is_numeric(end($params))) { // pattern /{#},offer.html
  8. $params[0] = '{#}';
  9. }
  10. if (is_numeric(end($params))) { // pattern /user,{id}.html
  11. $params[$paramsLength - 1] = '{id}';
  12. }
  13. if (!empty($paths)) {
  14. $paths = '/'.implode('/', $paths). '/';
  15. } else {
  16. $paths = '/';
  17. }
  18. return $paths . implode(',', $params) . '.html';
  19. }


oraz dispatch dla pn takiej reguły
  1. $router->addRoute('/your-website-title,site.html', [PageController::class, 'siteMethod']);

  1. public function dispatch(string $uri): void
  2. {
  3. $database = $this->database;
  4.  
  5. //$uri = $this->matchLocalhost($uri);
  6. $route = $this->matchRoute($uri);
  7. $uri = $route['uri'];
  8. $hasParams = false;
  9. if (!array_key_exists($uri, $this->routes)) {
  10. if (!empty($route['params'])) {
  11. $hasParams = true;
  12. $uri = $this->buildRouteUri($route['paths'], $route['params']);
  13. }
  14. }
  15.  
  16. if (array_key_exists($uri, $this->routes)) {
  17. $controller = $this->routes[$uri]['controller'];
  18. $method = $this->routes[$uri]['method'];
  19.  
  20. if (class_exists($controller)) {
  21. $controllerInstance = new $controller($database);
  22.  
  23. if (method_exists($controllerInstance, $method)) {
  24. if ($hasParams) {
  25. $controllerInstance->$method((int)end($route['params']));
  26. } else {
  27. $controllerInstance->$method();
  28. }
  29.  
  30. } else {
  31. throw new ExceptionHandler("No method $method on class $controller!", 500);
  32. }
  33. } else {
  34. throw new ExceptionHandler("No controller $controller!", 500);
  35. }
  36. } else {
  37. throw new ExceptionHandler("Route not found! addRoute('$uri')", 404);
  38. }
  39. }
Malinaa
Cytat(nospor @ 7.02.2024, 10:47:34 ) *
No ale jakies pytanie w zwiazku z tym czy tylko komunikujesz? wink.gif
No interfejsy daje sie w zasadzie wszedzie. u ciebie napewno na wszystko to co wstrzykujesz powinny byc interfejsy


Routing jest w trakcie budowy. Pierwsza wersja działa tylko na localhost po konfiguracji w kilku prostych krokach wg. instrukcji w README,
ale kiedy utworzyłem na Windows domenę dla testów okazuje się, że w domenie routing nie działa, więc muszę poprawić.

Są tu pozostałości z wersji pierwszej FW, np. /public/ .htaccess
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L] tego ?url=$1 nie powinno już być (było potrzebne przy sprytnej metodzie zamiast routingu)!?
Trzeba by pliki .htaccess w /public/ i katalogu głównym zrobić do porządku, aby routing działał na serwerze zdalnym i lokalnym.

Pozbyłem się sprytnej metody (która funkcjonowała jako routing na local i zdalnym) i utworzyłem na jej miejsce routing, który coś nie bardzo chce zadziałać na zdalnym.
Jeżeli przychodzi pomysł jak poprawić wymienione elementy, prośba o info.

Usuwając 'url' będą też inne metody do poprawienia, np. class DataFlatfile -> function fileName()
poza tym przy routingu wykorzystywany był define('APP_PATH', ''); co tez nie jest za dobrze, APP_PATH to raczej miało być używane dla szablonów mailera itp.
register-created-account.html -> {page_address} ale nie w routingu.

Interfejsy. No to od czego zaczniemy? smile.gif
Przydałby się pierwszy Interfejs, no tylko od czego zacząć.

Poznałem i przeanalizowałem ho, setki interfejsów, ale żebym który napisał. Ha ha mam okazje!
Jakie to proste, ale kiedy zacząć trzeba od podstaw?!

Jako, że aplikacja funkcjonuje już w pierwszej wymaganej opcji bez menedżera pakietów, można spróbować jak sobie radzi z Composerem.
Wgrałem PHPUnit, teoretycznie zainstalowane, ale gorzej z uruchomieniem testu, a przydałby się pierwszy test np. tego naszego połączenia z bazą danych.

Zaktualizowałem cały kod na Gicie z wersji 2.1 do 2.2 z nowym DI.
W logach miałem zero błędów. Przed wysłaniem sprawdziłem kod narzędziami od jakości kodu, wynik 0 błędów

Cytat(com @ 7.02.2024, 15:09:08 ) *
No i to jest pierwszy i podstawowy błąd...


Czyli kodowanie w czystym PHP uważasz za błąd? No, mając na względzie samą komercje, to masz racje, po prostu nie opłaca się pisać kodu od nowa kiedy są gotowce.
Czas jest cenny, ale pomijając komercyjne projekty może przyjmijmy, że mamy czas, ponieważ gotowce też nie wzięły się z powietrza.
Przyznam jednak, że jestem skłonny przyznać Ci racje bardziej niżeli słowom, które napisał Tomplus, ale generalnie macie podobnie racje smile.gif

To co może zakodujemy coś interesującego w PHP?!

Cytat
Chcę pomoc ale kompletnie nie zrozumiałeś przekazu, wysłałem Ci wartościowy materiał... Uparłeś się żeby stworzyć FW bez composera...


Dziękuje za chęci. Chyba nie oczekujesz, że ogarnę materiał, nad którym pracowałeś latami w tydzień (jednocześnie pisząc kod)... Uparłem się, no ok, ale nie prawdą jest że bez Composera itp. itd.
Obiecuję Ci smile.gif, że spróbuję ogarnąć przesłane materiały, ale kiedy przeczytam wszystkie treści, które chciałbym przeczytać to pójdę na psychologię, oczywiście programować sztuczną inteligencje No na psychologii to chyba wszystko można.

Cytat
Swoją droga nie można tego nawet uruchomić...

Sorki, nie ukończyłem prac nad routingiem, działa tylko na localhost w dowolnym katalogu, na domenie sypie się.

Cytat
Fajne logo...

Do logo wziąłem mapę Polski i jej obrys pokolorowałem na kolory, które pasowały do template.
Super, że fajne, a że wyszło podobne do JetBrains to nie grzech.

Cytat
To nie jest akurat SEO friendly...

Ok

Przesłałeś poprawki routingu, Wow. Spróbuję wdrożyć przesłany kod i zobaczę jak sobie poradzi w domenie.
Raczej przy weekendzie się tym zajmę, bo dzisiaj to już ogromny komercyjny zegar mnie goni.
nospor
Cytat
Interfejsy. No to od czego zaczniemy? smile.gif
Przydałby się pierwszy Interfejs, no tylko od czego zacząć.

Nie rozumiem jak to od czego zaczac?

Tworzysz interfejs o nazwie np. DatabaseInterface
Twoja klasa Database implentuje ten interfejs
class Database implements DatabaseInterace


a wszedzie tam w konstruktorach czy gdzie tam miales (Database $database) to teraz masz miec (DatabaseInterface $database)

No to sa juz podstawy interfejsow.
com
Cytat(Malinaa @ 8.02.2024, 11:44:53 ) *
Czyli kodowanie w czystym PHP uważasz za błąd? No, mając na względzie samą komercje, to masz racje, po prostu nie opłaca się pisać kodu od nowa kiedy są gotowce.
Czas jest cenny, ale pomijając komercyjne projekty może przyjmijmy, że mamy czas, ponieważ gotowce też nie wzięły się z powietrza.
Przyznam jednak, że jestem skłonny przyznać Ci racje bardziej niżeli słowom, które napisał Tomplus, ale generalnie macie podobnie racje smile.gif

To co może zakodujemy coś interesującego w PHP?!



Dziękuje za chęci. Chyba nie oczekujesz, że ogarnę materiał, nad którym pracowałeś latami w tydzień (jednocześnie pisząc kod)... Uparłem się, no ok, ale nie prawdą jest że bez Composera itp. itd.
Obiecuję Ci smile.gif, że spróbuję ogarnąć przesłane materiały, ale kiedy przeczytam wszystkie treści, które chciałbym przeczytać to pójdę na psychologię, oczywiście programować sztuczną inteligencje No na psychologii to chyba wszystko można.


Sorki, nie ukończyłem prac nad routingiem, działa tylko na localhost w dowolnym katalogu, na domenie sypie się.


Do logo wziąłem mapę Polski i jej obrys pokolorowałem na kolory, które pasowały do template.
Super, że fajne, a że wyszło podobne do JetBrains to nie grzech.


Ok

Przesłałeś poprawki routingu, Wow. Spróbuję wdrożyć przesłany kod i zobaczę jak sobie poradzi w domenie.
Raczej przy weekendzie się tym zajmę, bo dzisiaj to już ogromny komercyjny zegar mnie goni.


Nie uważam za kodowanie w czystym PHP za błąd, ale mówimy o zupełnie czymś innym, na tym polegać powinno kodowanie w czystym PHP https://tsh.io/blog/how-create-framework-ag...ication-in-php/ tylko to nie ten poziom wiedzy, wspomniałem o tym wcześniej już smile.gif najpierw trzeba poznać jakiś FW by potem pisać kod niezależny od niego, pisanie w czystym PHP to nie tworzenie własnego FW, bo nawet jak dla jakiegoś projektu musisz stworzyć jakiś SharedKernel czy Core w czystym PHP to nadal nie jest to pełnoprawny FW jaki teraz próbujesz stworzyć. Po prostu powinieneś używać tego tam gdzie ma to sens smile.gif

Jasne że możemy zakodować, ale z użyciem np Symfony/Laravel, pisząc logikę jako framework-agnostic, nie DbM Framework wink.gif

Ten materiał nie jest stworzony przez mnie, polecam Ci tylko wartościowe źródła z internetu które warto przestudiować, tym bardziej biorąc się za tworzenie FW, bez tych podstaw to się nie uda dobrze smile.gif

Wystarczyło pozbyć się tej metody i działa smile.gif

Co do logo jasne ale jak coś jest zbyt podobne do siebie to jest plagiat, wiec to grzech smile.gif

Poprawiłem ale dla wersji poprzedniej, widziałem że zrobiłeś zmiany w wersji 2.2 wiec musisz sobie poprawić różnice smile.gif



Pytasz o interfejsy, bo znów nie znasz tego pojecie, przez co nie wiesz jak to przełożyć na kod, musisz najpierw poczytać potem próbować coś zastosować w własnym kodzie smile.gif Jak zrozumiesz pojecie interfejsu to łatwo przyjdzie Ci go stworzyć, np dla przypadku o którym wspomniał nospor
Malinaa
Cytat(com @ 9.02.2024, 09:22:50 ) *
Nie uważam za kodowanie w czystym PHP za błąd... tylko to nie ten poziom wiedzy...


Pierwszy raz w tym poście słowo poziom jest jak najbardziej uzasadnione i tym razem bez dwóch zdań przyznam (mimo że nie powinienem) - masz racje.
Gdybym miał większą wiedzę, o której piszesz nie bawiłbym się frameworkami, a od razu zajął sztuczną inteligencją smile.gif
ale póki co pozwól, że stworzę kod, który jak rozumiem tylko dla mnie ma sens - jest mi potrzebny jak WordPress 60 procentom Internetu
(chociaż 10 lat temu ostatni raz użyłem tego kodu, bo kiedy go zobaczyłem i napisałem kilka wtyczek uznałem, że nie ma sensu iść tą "ślepą" drogą),
poza tym może zostańmy przy temacie postu frameworkach nie koniecznie autorskich wink.gif a Symfony i Laravel.
Powstaje odwieczne pytanie sensu... podążania tą drogą?

P.S. Dziękuje za przesłanie poprawek routingu, sprawdziłem śmiga w domenie,
jeszcze zajrzę jak chodzi na localhost, no i można poczytać o interfejsach itd... I nastała jasność.
com
Cytat(Malinaa @ 9.02.2024, 11:38:31 ) *
Pierwszy raz w tym poście słowo poziom jest jak najbardziej uzasadnione i tym razem bez dwóch zdań przyznam (mimo że nie powinienem) - masz racje.
Gdybym miał większą wiedzę, o której piszesz nie bawiłbym się frameworkami, a od razu zajął sztuczną inteligencją smile.gif
ale póki co pozwól, że stworzę kod, który jak rozumiem tylko dla mnie ma sens - jest mi potrzebny jak WordPress 60 procentom Internetu
(chociaż 10 lat temu ostatni raz użyłem tego kodu, bo kiedy go zobaczyłem i napisałem kilka wtyczek uznałem, że nie ma sensu iść tą "ślepą" drogą),
poza tym może zostańmy przy temacie postu frameworkach nie koniecznie autorskich wink.gif a Symfony i Laravel.
Powstaje odwieczne pytanie sensu... podążania tą drogą?

P.S. Dziękuje za przesłanie poprawek routingu, sprawdziłem śmiga w domenie,
jeszcze zajrzę jak chodzi na localhost, no i można poczytać o interfejsach itd... I nastała jasność.


Żeby dziś znaleźć prace trzeba jeden z nich znać, a zakładam że kiedyś będziesz chciał pracować jako programista, skoro próbujesz się tego uczyć? FW to tylko narzędzie, jak młotek do wbijania gwoździ, jak nie będziesz potrafił jego obsługiwać to zrobisz sobie krzywdę, z FW jest tak samo. Jak już potrafisz go używać to wtedy czas na gwoździarkę i tu jest tak samo, poznajesz nowe rzeczy, zaczynasz pisać kod zgodny z ideą DDD, stajesz się framework-agnostic itp smile.gif

Super że działa, ciesze się i fajnie że zaczynasz słuchać o tym żeby poczytać smile.gif
Malinaa
Cytat(nospor @ 8.02.2024, 12:24:30 ) *
Tworzysz interfejs o nazwie np. DatabaseInterface
Twoja klasa Database implentuje ten interfejs
class Database implements DatabaseInterace


Ogólnie jak działają interfejsy to wiem, w praktyce wyszło o czym nie wiedziałem, ale już też zrobione.
Interfejsy utworzone. Coś chyba jeszcze jest nie tak, ponieważ w np.

DatabaseInterface

public function queryExecute(string $query, ?array $params = [], bool $reference = false): bool;

kiedy zmienię na bool $reference bez wartości w Visualu pojawia się chmurka: Expected 3 arguments, Found 2.

Aplikacja działa ok, ale Visual coś pokazuje nie ok?


Cytat(com @ 9.02.2024, 12:19:11 ) *
Super że działa, ciesze się i fajnie że zaczynasz słuchać o tym żeby poczytać smile.gif

O interfejsach poczytane, chociaż powtarzają się w Necie te same podstawy i za wiele poza tym o czym napisał nospor się nie dowiedziałem, ale zawsze to coś nowego.

Routing jeszcze nie daje spokoju, ponieważ linki nie są SEO friendly, np. present-eusmod-grvd-lbero-luctus-ns-fermentum-nec,art,5.html
Jaka byłaby najlepsza opcja z końcówką .html, może /art/5/present-eusmod-grvd-lbero-luctus-ns-fermentum-nec.html
ale ze slashami w adresie i prawidłową ścieżką był zawsze kłopot w przeglądarce ?
Salvation
Cytat(Malinaa @ 12.02.2024, 00:27:30 ) *
public function queryExecute(string $query, ?array $params = [], bool $reference = false): bool;

A po co Ci wartości domyślne w Interface? Rzadko się takie coś robi, bo powinno się świadomie wypełnić parametr.

Cytat(Malinaa @ 12.02.2024, 00:27:30 ) *
kiedy zmienię na bool $reference bez wartości w Visualu pojawia się chmurka: Expected 3 arguments, Found 2.

Aplikacja działa ok, ale Visual coś pokazuje nie ok?

Wartość domyśla pozwala pominąć argument przy wywołaniu metody. Dostajesz informację z IDE, że źle wywołujesz metodę.

Czyli w Twoim przypadku poprawne będzie skorzystanie z takich wywołań:
  1. queryExecute('query');
  2. queryExecute('query', null);
  3. queryExecute('query', null, true);
  4. queryExecute(query: 'query', reference: true); // dla PHP 8


A to czy "aplikacja działa ok", bez podania ostatniego parametru w metodzie, powinno wyjść przy testach, które pewnie napisałeś?
Malinaa
Cytat(Salvation @ 12.02.2024, 09:24:26 ) *
1. Czyli w Twoim przypadku poprawne będzie skorzystanie z takich wywołań:
2. A to czy "aplikacja działa ok", bez podania ostatniego parametru w metodzie, powinno wyjść przy testach, które pewnie napisałeś?


1. Jasne, tylko po co w każdym wywołaniu metody pisać (dodawać false/true)
$this->database->queryExecute($query, [':limit' => $limit], false); ?
jeśli tak jest krócej i prościej $this->database->queryExecute($query, [':limit' => $limit]);

kiedy mimo, że rzadko się tak robi w interfejsie można dać: public function queryExecute(string $query, ?array $params = [], bool $reference = false): bool;
nie public function queryExecute(string $query, ?array $params = [], bool $reference): bool; i jest ok.

2. Dla testów dodałem ExampleTest.php wywołałem "composer test", aby sprawdzić czy działają i jest OK (1 test, 1 assertion), czyli testować też można.
Natomiast jeżeli chcesz mnie nauczyć pisania testów to możemy zrobić kolejny test np. DatabaseTest.php, ale to nie będzie takie proste.
No kto pisze testy wink.gif ale pewnie, że byłoby warto coś przetestować.

Może jakieś pomysły jak powinien wyglądać idealny seo friendly link dla przykładowego z końcówką .html
/art_5_present-eusmod-grvd-lbero-luctus-ns-fermentum-nec.html - z podkreślnikiem nie za bardzo wygląda, a ze slasem jest kłopotliwy ?
Wydawało się, że przecinek będzie zgodny z seo podobnie jak kropka, ale jak się okazuje, przecinek nie, więc jak by to zrobić..
Robiłem kiedyś split testy i wyszło, że największa klikalność była dla linków z końcówką typu domain.com/key-word-etc.html
a 10 % więcej potencjalnych klientów, może oznaczać że zamiast zarabiać 100 mamy 110, 1000 -> 1100, 10 000 -> 11 000 zł, więc spora różnica na plusie.
Przydałaby się konstrukcja linków, w które klikamy bez opamiętania i nie trzeba używać słów typu: best-sex-in-life.html smile.gif
Salvation
Cytat(Malinaa @ 12.02.2024, 20:27:50 ) *
1. Jasne, tylko po co w każdym wywołaniu metody pisać (dodawać false/true)
$this->database->queryExecute($query, [':limit' => $limit], false); ?
jeśli tak jest krócej i prościej $this->database->queryExecute($query, [':limit' => $limit]);

kiedy mimo, że rzadko się tak robi w interfejsie można dać: public function queryExecute(string $query, ?array $params = [], bool $reference = false): bool;
nie public function queryExecute(string $query, ?array $params = [], bool $reference): bool; i jest ok.

Przyjęło się - i takie też są zalecenia - że ergumenty metody z domyślną wartością lądują na końcu. A nic nie staje na przeszkodzie, żeby Interface wyglądał po bożemu:
  1. public function queryExecute(string $query, ?array $params, bool $reference): bool;

A klasa, która go implementuje wyglądała tak:
  1. public function queryExecute(string $query, ?array $params = null, bool $reference = false): bool;

Demo: https://3v4l.org/00aAp

Cytat(Malinaa @ 12.02.2024, 20:27:50 ) *
2. Dla testów dodałem ExampleTest.php wywołałem "composer test", aby sprawdzić czy działają i jest OK (1 test, 1 assertion), czyli testować też można.
Natomiast jeżeli chcesz mnie nauczyć pisania testów to możemy zrobić kolejny test np. DatabaseTest.php, ale to nie będzie takie proste.
No kto pisze testy ;) ale pewnie, że byłoby warto coś przetestować.

Kto pisze testy? Przedewszystkim twórcy frameworków. Polecam podejście TDD. Znacznie mniej kodu się produkuje i - prawie - od razu wchodzisz w SOLIDy kod.
Malinaa
Cytat(Salvation @ 13.02.2024, 11:34:58 ) *
A nic nie staje na przeszkodzie, żeby Interface wyglądał po bożemu:


No, o tym pisałem wcześniej, że staje na przeszkodzie, bo Visual wyświetla chmurkę, że brakuje argumentu,
dlatego dałem tak samo jak w klasie bool $reference = false.

Jeżeli w interfejsie dam bool $reference aplikacja działa, teoretycznie jest ok, ale Visual pokazuje nie ok.

Kiedy napiszę w klasie i interfejsie bool $reference = false nie ma problemu, wszystko na zielono Ok.
Chyba, że jest coś jeszcze, może jakoś powtarzają się metody, wczytywane są 2x te same?
Raczej nie chciałbym w każdej metodzie dodawać false: $this->database->queryExecute($query, [':limit' => $limit], false);
ale dlaczego kiedy zmienię interfejs na bez false: public function queryExecute(string $query, ?array $params = [], bool $reference): bool;
w Visualu świeci na czerwono?

Testy, to może przy weekendzie zobaczę, czy coś da się zrobić,
chyba, że byłbyś tak dobry i napisał przykład dla Database.php?
Byłoby prościej próbować kolejne.

Adres SEO Friendly - coś nie widać pomysłów?
Teoretycznie z tego co widzę można tworzyć linki z podkreśleniem, chociaż nie jest zalecane:
przykład: /art_5_present-eusmod-grvd-lbero-luctus-ns-fermentum-nec.html
trochę też tak sobie wygląda z tymi podkreśleniami, może jakiś inny znak (dozwolony w seo linku), alko ze slasem
/art/5/present-eusmod-grvd-lbero-luctus-ns-fermentum-nec.html fajnie wygląda, tylko tutaj mam kłopot taki, ze przeglądarka traktuje ścieżkę jakby strona (statycznie) była w katalogu /art/5/
i wówczas trzeba przerabiać path np. przy wyświetlaniu obrazków na ../../images/ aby wejść do katalogu, podobnie dla ../../assets/ oraz podstron, itd...
Czy jest jakieś sprytniejszy sposób? Aby mieś 100% SEO i nie kombinować z path'em!
viking
Zaczynając od php 8.0 wszystkie parametry required muszą być zdefiniowane pierwsze.
A nawet jak zdefiniujesz public string $a, public ?string $b = null, public string $c to automatem php przerobi $b na wymagany.
Salvation
Cytat(Malinaa @ 13.02.2024, 20:46:10 ) *
dlaczego kiedy zmienię interfejs na bez false: public function queryExecute(string $query, ?array $params = [], bool $reference): bool;
w Visualu świeci na czerwono?

Cytat(Salvation @ 13.02.2024, 11:34:58 ) *
Przyjęło się - i takie też są zalecenia - że argumenty metody z domyślną wartością lądują na końcu.


Jak zrobisz to w ten sposób co proponujesz, to `$params` będzie required (choć kod na to nie wskazuje), więc jak podasz tylko dwa argumenty w wywołaniu, to otrzymasz błąd w IDE. Ale widzę, że już Viking mnie uprzedził :D
Mam wrażenie też, że nie do końca ogarniasz OOP. Dlaczego uparłeś się mieć wartości domyślne w Interface?
Malinaa
Cytat(viking @ 14.02.2024, 09:24:11 ) *
Zaczynając od php 8.0 wszystkie parametry required muszą być zdefiniowane pierwsze.


Nie inaczej required są pierwsze.

W przykładzie ostanie false mogło być mylące, dokładnie całość w interfejsie chciałem dać tak:

public function queryExecute(string $query, array $params, bool $reference): bool;

gdzie tylko $query jest required (jeden pierwszy argument)

ale wówczas np. w BlogModel.php Visual pokazuje chmurkę, że nie widzi wszystkich argumentów

dlaczego wyskakuje chmurka - ponieważ w BlogModel.php jest construct z DatabaseInterface i po zmianie na siłę trzeba wrzucać w metodę false
a chyba nie po to był pisany interfejs, aby w konstruktor wstrzykiwać klasę Database, albo w metodę nie wymagane false/true? Jak to napisał wcześniej Salvation.


Cytat
Jak zrobisz to w ten sposób co proponujesz...


Zmieniłem na sposób, który zaproponowałeś, bo "tak się przyjęło"... i elegancko. Aplikacja działa; kłopot, że w Visualu świeci na czerwono.

Kod jest dostępny. Jak nie ma kodu, to podaj kod, kiedy jest kod to nie można do niego zajrzeć?
Coś tu nie rozumiem.

Może lepiej podam kod krok po kroku, bo chyba można ten kod ze sobą "pogodzić".

Klasa Database.php

Kod
public function queryExecute(string $query, ?array $params = [], bool $reference = false): bool
{
...
}


Interfejs DatabaseInterface.php był tak samo jak w klasie, ale chcemy, aby był tak:

Kod
public function queryExecute(string $query, array $params, bool $reference): bool;
{
...
}


i ok, zmieniam na powyższy - aplikacja działa, teoretycznie wszystko ok, ale przechodzę do
modeli, np.: BlogModel.php -> Visual wyświetla chmurkę -> brakuje argumentów w metodzie queryExecute()

I tutaj jest problem, no ale w konstruktorze miałem: public function __construct(DatabaseInterface $database) -> brak zgodności więc Visual świeci na czerwono,
no dobrze, ale generalnie nie ma problemu zmieniam konstruktor na:

Kod
public function __construct(Database $database)
{
...
}


i wszystko działa, w Visualu też wszystko jest na zielono, ok.

Przy czym w kontrolerach np. BlogController.php w konstruktor wstrzykiwany jest interfejs

Kod
public function __construct(DatabaseInterface $database)
{
...
}



Pytanie, czy tak jest dobrze, że mając interfejs w konstruktor modeli wstrzykuję klasę Database nie interfejs DatabaseInterface,
ewentualnie jak prawidłowo pogodzić te klasy i metody z klasą Database i interfejsem DatabaseInterface?
Tutaj coś nie wiem, które rozwiązanie jest dobre.
Czy w modelach może tu być w konstruktorze Database zamiast DatabaseInterface, bo ta zamiana rozwiązuje problem wyświetlania przez Visual chmurki z info o brakujących argumentach metody.

Chciałbym ogarnąć jeszcze miejsca w kodzie, gdzie zostało dodane TODO!
I trafiam na taką funkcje, która to była jako tymczasowa dla szablonów i jest powiązana z Database, które jak widać z powyższego jeszcze szwankuje.

plik template.php

Kod
// TODO! Temporary function
use Dbm\Classes\Database;

function temp_htmlUser($sessionUserId, $module = null, $tempPath = null): string
{
    $database = new Database(); // TODO!
    ...
}


Jak to zrobić, aby było ok dla szablonów, w których chciałbym mieć tylko funkcje do obsługi szablonu, np. path() itp. gdzie temp_htmlUser() wymaga połączenia z bazą danych?
nospor
Cytat
Jak to zrobić, aby było ok dla szablonów, w których chciałbym mieć tylko funkcje do obsługi szablonu, np. path() itp. gdzie temp_htmlUser() wymaga połączenia z bazą danych?

No toz dopiero co przerabialismy DI. Skoro jakas twoja tam funkcja potrzebuje obietku DB to masz go pokolei przekazywac az dojdzie do tej funkcji. Zasada sie nie zmienia.

To po pierwsze.
A po drugie funkcja template nie powinna nic wiedziec o bazie. Ona tylko powinna dostac dane niezbedne do wygnerowania szablonu
Malinaa
Tak przerabialiśmy i wiem jak mógłbym to zrobić dla klasy, ale tu są tylko funkcje.

Jest plik index.php w folderze public, tu wczytuje:
require(BASE_DIRECTORY . 'application' . DS . 'template.php');
w pliku template.php dodaje funkcje dla szablonów
i idąc po kolei, pierwszy szablon base.phtml w folderze templates wstawiam jakie potrzebuje funkcje,
pierwsza z góry <?= trans('lang') ?> itd. i mogłoby tak być, aż dojdziemy do
templates/_include/navigation.phtml linia 52 funkcja echo temp_htmlUser() (gdzie temp oznaczyłem jako temporary -> TODO! nie template)
w tej funkcji docelowo htmlUser() potrzebne jest pobranie danych z bazy danych i tutaj mój system szablonów w wersji pierwszej już wymięka.

Czy można ten system zostawić na funkcjach i pobrać obiekt DB dla funkcji, czy tutaj już muszę przerobić cały system na klasę? Plik template.php z funkcjami na Class -> Template.php
Kłopot przy przerabianiu jest taki, że chyba będę musiał poprawić też wszystkie szablony, ponieważ wówczas w wymienionym
base.phtml już nie będę mógł zrobić tak <?= trans('lang') ?> jak bym chciał, a raczej <?= $object->trans('lang') ?>

I tak zaglądam jak to zrobić, aby było dobrze. Prawdopodobnie to co mam jeszcze w pliku public/index.php jako funkcje

### FUNCTIONS - application starting, template engine, etc.
require(BASE_DIRECTORY . 'application' . DS . 'start.php');
// Default template engine, you can change it to any other one
require(BASE_DIRECTORY . 'application' . DS . 'template.php');

i tak będzie trzeba zmienić na klasy, ponieważ z tymi funkcjami to za dobrze nigdy nie będzie?
Tylko to oznacza konieczność przerobienia też wszystkich szablonów .phtml, wywołania funkcji <?= trans('lang') ?> i każdej innej,
no chyba, że może zostać <?= trans('lang') ?> itd. oraz htmlUser() <- DB ?

Tak na to jeszcze raz zajrzałem i jak mam zaś po kolei przerabiać te szablony to mi ręce opadły, dobrze byłoby wiedzieć jak zrobić teki system szablonów, co by teraz zaś nie wałkować szablon po szablonie...
nospor
Jak ty sobei lubisz komplikowac prace
I co z tego ze tu masz funkcje a tam miales klasy? Przeciez tam w klasach i tak przekazywales DB do funkcji, ktora sie nazywala __construct, ale to nadal byla funkcja.

Skoro teraz masz:
function temp_htmlUser($sessionUserId, $module = null, $tempPath = null): string

a potem wywolanie
echo temp_htmlUser($this->getSession('dbmUserId'));

To czemu nie zrobisz analogicznie z db?


function temp_htmlUser($sessionUserId, DatabaseInterfacce $db, $module = null, $tempPath = null): string

a potem wywolanie
echo temp_htmlUser($this->getSession('dbmUserId'), $this-getDatabase());

Skoro w kontrolerze masz metode getSession to przeciez mozesz tam dodac metode tez getDatabase(). Przeciez kontroler ma juz obiekt DB wiec metoda getDatabase musi go tylko zwrocic. I juz
Malinaa
Tak jakoś mam, że i tu gdzie można by przyjąć, że nie ma już problemu, pojawiły się znaki zapytania komplikujące dokończenie dzieła wink.gif

Bo wiesz wcześniej to miałem te szablony z końcówką typu base.html.php i funkcje (trans(), path(), htmlUser(), dalej $this->getSession() itp.) w tych plikach wydawały mi się ok,
ale zmieniłem rozszerzenie szablonów na końcówkę base.phtml i tak się zawiesiłem na tym, czy te funkcje w tych plikach są w ogóle ok?!

Dzięki za info. Jeżeli funkcje są tu ok, to problem z głowy,
no może jeszcze tylko z takim drobiazgiem co zrobić
i "sprzątam" pozostałe znaki zapytania oznaczone w kodzie TODO!

Kod
use Dbm\Interfaces\DatabaseInterface;

function htmlUser(DatabaseInterface $database, int $sessionUserId, string $module = null): string
{
...
}


Jeśli w funkcji dam DatabaseInterface $database to muszę dodać use Dbm\Interfaces\DatabaseInterface co nie wygląda rewelacyjnie w tym pliku template.php.

nospor
Cytat
Jeśli w funkcji dam DatabaseInterface $database to muszę dodać use Dbm\Interfaces\DatabaseInterface co nie wygląda rewelacyjnie w tym pliku template.php.

Skoro uzywasz DB w pliku template.php to nie masz wyjscia.
Malinaa
Używam, choć przyszedł mi na myśl inny system szablonów. Jakiś gotowiec! Ciekawe, który by się tu nadawał najbardziej?

1.W tym pliku może pominę typowanie argumentów dla funkcji
function htmlUser($database, $sessionUserId, $module = null): string {}
wówczas nie trzeba dodawać 'use' co wygląda tu lepiej.

Kod prawie posprzątany, zostało zapytanie:

2. Czy można tu w zapytaniu użyć "SELECT roles FROM dbm_user WHERE id = ?"
czy bezpieczniej będzie "SELECT roles FROM dbm_user WHERE id = :id".
Jak to jest z :id lub znakiem zapytania w zapytaniu, czy tak samo bezpieczne?

Kod
public function userPermissions(int $id): ?string
    {
        $database = $this->database;
        $query = "SELECT roles FROM dbm_user WHERE id = ?"; // TODO! Jak to jest z :id lub znakiem zapytania, czy tak samo jest bezpieczne?
        ...
    }


3. Problem powstały przy napisaniu interfejsów. Jakby to zapytać możliwie najkrócej, które rozwiązanie wybrać.

Czy w
Kod
class BlogModel
{
    private $database;

    public function __construct(DatabaseInterface $database)
    {
        $this->database = $database;
    }

można wstrzyknąć: public function __construct(Database $database) klasę nie interfejs i będzie Ok?

Po tej zmianie można tez zmienić metody w interfejsie na pożądane, czyli bez wartości
public function queryExecute(string $query, ?array $param, bool $reference): bool;
zamiast
public function queryExecute(string $query, ?array $params = [], bool $reference = false): bool;
i jest czysto, bez błędów.
Natomiast jeżeli ma być DatabaseInterface $database w modelach to interfejsy zostają z wartościami,
bo nie wiem jak inaczej całość pogodzić.

Z tego co przejrzałem kod są to 3 ostatki do poprawienia oznaczone TODO i powinno być OK.
Bynajmniej na ten czas, no chyba, że przyjdzie pomysł na dalszą rozbudowę wink.gif
nospor
ad2) bez znaczenia


Na pozostale dwa juz nie wiem czy mam sile odpowiadac.... Nie poto wprowadzilismy interfejsy zebys je teraz radosnie usuwal bo wizualnie ci sie nie podoba w templates masz use DB. No kurde.... juz ci dawno pisalem ze template nie powinien nic weidziec o DB, tylko dostac dane niezbedne do wygenerowania widoku i wtedy nie masz w ogole DB tam. No ale jak sie nie slucha to sie ma jak ma

Zas co do chmurek w twoim edytorze to tez nie ogarniam. Zmien edytor. Mi phpstorm nie pokazuje zadnuch chmurek czy bledow.

Nie ogarniam tez czemu tak na ciebie siedli za te wartosci defaultowe w interfejsie. A juz w ogole nie rozumiem czemu kaza ci default kasowac w interfejs a zostawic w klasie. No to juz w ooggole nieporozumienie, bo jak kiedys dojdzie inne klasa ktora implementuje interfejs ale tym razem bez defaultow tak mowi interfejs, to kod ci sie wywali bo jakies kawalki kodu beda jechac po starej klasie gdzie byly default. I zonk.
Malinaa
2. Ok i super.

1. Ach, dasz radę. Ten template jest light weight smile.gif

Nie jest tak jak piszesz, albo coś nie kumam.
Zgodnie z tym co pisałem w template.php nie ma use DB nie ma też już use Interface,
usunąłem tylko typowanie z funkcji
function htmlUser($database, $sessionUserId, $module = null): string {}
nigdzie nie było powiedziane, że każda funkcja musi mieć typowanie, więc jest oki.

Wywołanie funkcji jest m.in. w navigation.phtml
echo htmlUser($this->getDatabase(), $this->getSession(''));
gdzie $this->getDatabase() jest w BaseController.php wstrzykiwane z interfejsu DatabaseInterface $database nie klasy DB (Database).

Chyba, że chcesz, aby zamiast $database, dać jakąś tablice z danymi usera: id, login, avatar itd...
No to akurat w przypadku tej funkcji "globalnej" (i używanej w różnych miejscach) jest mocno kłopotliwe, jeszcze nie wiem, ale raczej musiałby tu dodać jakiś nowy mechanizm,
coś jak w Symfony -> TwigExtension, albo coś za dużo sobie wyobrażam i można prościej.

Ale po co Extension itd. kiedy $this->getDatabase() idzie z interfejsu i załatwia sprawę?!

3. Czemu miałbym usuwać wartości defaultowe w interfejsie, które są w klasie - była informacja, że tak się przyjęło (no i mus, nie ma rady).
Może tak, program działa bez tych wartości, ale nawet Visual podpowiada, że po usunięciu domyślnych wartości coś nie do końca zagrało z interfejsem i klasą.
A piszesz, że lepiej jest dokładnie napisać interfejs zgodny z klasą też w defaultowych wartościach, co wbrew temu co się przyjęło będzie pomocne przed zonk'iem.
Pomijając Visual Twoja informacja utwierdza mnie w przerkonaniu, że te defaultowe wartości powinny tam być, wiec zostawiam interfejs tak jak utworzyłem.

Znalazłem jeszcze jedno TODO

Kod
private function paramType($value)
    {
        switch (true) {
            case is_null($value):
                return PDO::PARAM_NULL;
                break;
            case is_int($value):
                return PDO::PARAM_INT;
                break;
            case is_bool($value):
                return PDO::PARAM_BOOL;
                break;
            default:
                return PDO::PARAM_STR;
        }
    }

Jak zapisać typowanie dla tej metody, spróbowałem z mixed, ale wówczas się sypie
private function paramType(mixed $value): mixed ?
nospor
Cytat
Nie jest tak jak piszesz, albo coś nie kumam.
Zgodnie z tym co pisałem w template.php nie ma use DB nie ma też już use Interface,

No nie ma bo usunales. O tym wlasnie mowie...nie po to wprowadzalismy interfejsy bys teraz radosnie je usuwal bo ci sie nie podoba use w twoim pliku.

Cytat
nigdzie nie było powiedziane, że każda funkcja musi mieć typowanie, więc jest oki.

X postow wczesniej plakales ze musi to byc zrobione perfekcyjnie,teraz cos usuwac bo cie sie wizualnie nie podoba use.

Ja mam dosc. Milego smile.gif
Malinaa
Tak chcę, aby było bezbłędnie. Czy będzie perfekcyjnie jeśli dodam w pliku template.php use Dbm\Interfaces\DatabaseInterface? Myślę, że nie, jeżeli usunę też nie, więc po co się nad tym rozwodzić.
Pewnie, aby było dobrze i tak będę musiał dopisać klasę Template (zamiast tych funkcji), albo użyć gotowego silnika szablonów.
Wówczas rzeczywiście oddzielę ten widok tak jak wcześniej pisałeś i template nie będzie nic wiedzieć o DB.

Przy tym template trochę mnie odcięło (coś tam usunąłem, dodałem, już nie pamiętam), ale przypakowałem na siłce i mocy przybyło, jak nie siłka to Red Bull doda Ci skrzydeł.

P.S. Podaj adres podeślę Ci śniadanie. Jeżeli nie masz siły spróbuj coś innego, dobrego i poczujesz się o niebo lepiej smile.gif
Dzięki za pomoc. Pozdrawiam serdecznie

Dopisuje klasę TemplateEngine, wówczas można przyzwoicie dodać use Dbm\Interfaces\DatabaseInterface; kod umieściłem pod linkiem:
https://github.com/artimman/dbmframework/tr...nts/Template_v1
w pliku public/index.php odznaczam linie
//require(BASE_DIRECTORY . 'application' . DS . 'template.php');
przechodzę do BaseController w application/classes gdzie dodałem extends TemplateEngine

Sprawdzam jak działa templates/base.phtml i yield'y, include, extends jest ok, pozostało {{ $this->trans('lang') }}
Czy ktoś ma może pomysł jak sprawić, aby w szablonach działało {{ trans('lang') }} i/lub podobnie?
Zostało dopisanie mechanizmu, którym można wywoływać metody klasy jak funkcje w szablonach bez $this (->nazwaMetody).
Mam nadzieję, że wówczas i szablony będą zakodowane w porządku.
nospor
Cytat
Sprawdzam jak działa templates/base.phtml i yield'y, include, extends jest ok, pozostało {{ $this->trans('lang') }}
Czy ktoś ma może pomysł jak sprawić, aby w szablonach działało {{ trans('lang') }} i/lub podobnie?


Jak zwykle nie kumam
Skoro ten kod

private function compileEchos(string $code): string
{
return preg_replace('~\{{\s*(.+?)\s*\}}~is', '<?php echo $1 ?>', $code);
}

ci obsluguje {{$this->metoda}}
to wywal $this i dodaj do echo

private function compileEchos(string $code): string
{
return preg_replace('~\{{\s*(.+?)\s*\}}~is', '<?php echo $this->$1 ?>', $code);
}


ps: dalej tworzysz potworki ala:

if (..) {
...
return ...
} else {
return ...
}

Nauki ciagle ida w las
Malinaa
Gadanie, kumasz. Chociaż szczęście każdy rozumie na swój sposób smile.gif

return preg_replace('~\{{\s*(.+?)\s*\}}~is', '<?php echo $1 ?>', $code);

działa prawidłowo i jest potrzebne np. w pętli
{% foreach($colors as $color): %}
<li>{{ $color }}</li> <- jest elegancko
{% endforeach; %}
więc może nie ruszajmy tego co funkcjonuje dobrze.

na podanym kodzie
return preg_replace('~\{{\s*(.+?)\s*\}}~is', '<?php echo $this->$1 ?>', $code);
wyskakuje błąd

dopisałem taki kod
Kod
private function extensionPath(string $code): string
    {
        return preg_replace('~\{@\s*path(.+?)\s*\@}~is', '<?php echo $this->path($1) ?>', $code);
    }

    private function extensionTrans(string $code): string
    {
        return preg_replace('~\{@\s*trans/((.+?),(.+?),(.+?)/)\s*\@}~is', '<?php echo $this->trans($1,$2,$3) ?>', $code);
    }


w szablonie
{@ path('test/') @}
{@ trans('lang', [], []) @}
dla path() wygląda, że idzie, ale dalej przy funkcjach z wieloma argumentami trans() to nie wiem

poza tym trzeba te wszystkie metody wklepywać m.in. to compileCode(), co nie jest fantastycznym "mechanizmem",
ale nie widzę tu prostego rozwiązania i preg_replace() nie wystarczy, musiałby chyba tworzyć jakąś machine do obsługi takich custom funkcji?

No nie wygląda ten silnik szablonów rewelacyjnie z $this wszędzie, szablon jest zapchany $this'em,
ale jeżeli nie przeszkadza, nie obciąża systemu to może tak zostawić?


Powtórki jak się domyślam w class Database

Pytałem o function paramType($value), brak informacji na temat typowania dla takiej metody, gdzie return jest "mixed" - PHP 7, w 8 może wystarczyło by dać tylko mixed, chociaż z mixed to i tak nie wiadomo - skłoniło mnie do if and else, aby nie zostawiać metody bez typowania w klasie, gdzie każda metoda ma typowanie. Nauka nie idzie w las, takie pragmatyczne rozwiązanie. Poza tym to nie samolot, śmiga chociaż nie ma "skrzydeł".
nospor
Cytat
wyskakuje błąd

Juz ci kiedys pisalem co masz zrobic gdy wyskakuje blad. I znowu, gadam w proznie

Cytat
Powtórki jak się domyślam w class Database

No wlasnie zle sie domyslasz. Nie mam czasu ogladac za kazdym razem calego twojego kodu. Skoro mowiles o szablonach to i ja spojrzalem tylko na szablony i tam wlasnie takie potworki byly
Malinaa
Pamięć dobra, ale krótka o czym kiedyś pisałeś co zrobić gdy wyskakuje błąd. Takie podsumowanie, że już nie kumam.
Wolałbym się nad tym nie rozwodzić, but life is brutal and full of zasadzkas and sometimes kopas w dupas... tylko zgredzi nic nie kumają that there are beautiful moments in life, so let's enjoy life before old age hunt down you

Funkcje w szablonach mogą być jeszcze z wersji pierwszej, sprzed tego o czym pisałeś. Potem zobaczę do tych funkcji, przy optymalizacji i spróbuje według nowych wytycznych poprawić powtórki.
Na ten czas poprawiałem TODO w kodzie i wyszły te szablony do zrobienia.

Problem nie jest w samym błędzie, to można poprawić, ale poprawianie tego błędu nie wiele daje, gdyż funkcją preg_replace() której dotyczy błąd nie rozwiąże problemu rozszerzenia szablonów o dodatkowe funkcje, funkcjonalność.
Raczej przydałby się kolejny mechanizm dla takiego rozszerzenia. Chyba, że wystarczy poprawić preg_replace(),, dodać jakąś pętle itp. Wystarczy jedna sprytna metoda, nie potrzebnie tu kombinuje, bo nie wiem jak dopracować ten silnik szablonów?

Z tego co poczytałem $this w templates to nie kłopot, więc decyduje się na takie rozwiązanie, gdzie this/y będą tak <?= $this->trans('lang') ?>
https://github.com/artimman/dbmframework/bl...ates/base.phtml
i powinno być Ok, lepsze niż kombinacje z preg_replace(), poza tym w znacznikach <?php ?> zawsze zadziała, natomiast kompilowane przez funkcje to już zależy na co trafi.

Dzięki dodaniu klasy TemplateEngine rozwiązany został problem w pliku template.php use Dbm\Interfaces\DatabaseInterface
oraz aplikacja rozbudowana została o takie mechanizmy jak kompilator szablonów i cache.

Jeżeli teraz szablony są Ok pozostały drobne pytania (oznaczone TODO)
1. private static $blocks = array(); Zastanawiałem się nad static array, ale powinno być Ok?
2. w Necie wyczytałem, że nie powinno się używać PHP_EOL należy użyć "/n"? Przy formatowaniu kodu HTML zakładam, że lepiej jest użyć PHP_EOL, wówczas powinno wykonać to samo w każdym systemie.

P.S. Usunąłem kilka powtórek else, które wyłapałem, że są do poprawienia.
Już sobie przypominam kiedy wyskakuje błąd, to wrzucić kod i komunikat błędu. Ok, ale tak tylko sobie "głośno" myślałem co z tym zrobić i problem rozwiązany.
Sorki, że dopytuje o takie szczegóły jak PHP_EOL, ale w Sieci jak taka ilość różnych informacji, że czasem trudno rozróżnić co jest dobre, a co nie.
nospor
Cytat
Sorki, że dopytuje o takie szczegóły jak PHP_EOL, ale w Sieci jak taka ilość różnych informacji, że czasem trudno rozróżnić co jest dobre, a co nie.

A gdzie ty chcesz uzywac tego PHP_EOL? Bo ciezko mi sobie wyobrazic gdzie ci jest potrzebne

INna sprawa ze nie zastanawiasz sie nad kodem ktory piszesz. W wielu miejscach masz

<?= trans('charset') ?>
czyli wywolujesz funkcje trans() petryliard razy. A co robi funkcja trans?
za kazdym razem robi
require($pathTranslation);
no tak nie mozna.... Wczytaj plik raz, jego przerobine dane trzymaj w obiekcie i korzystaj z nich a nie za kazdym razem przerabiasz ten sam proces. A require to tylko jezna z nieicznych rzeczy ktore bez sensu powtarzac odpalajac trans()
Malinaa
Użycie PHP_EOL w TemplateEngine

Kod
file_put_contents($cachedFile, '<?php class_exists(\'' . __CLASS__ . '\') or exit; ?>' . PHP_EOL . $code);


Kolejny kod, w którym chcę używać zamiast "\n", metody w TemplateFeature, np.

public function htmlUser(
...
$html .= '<img class="dbm-img-profile rounded-circle" src="' . $this->path() . 'images/avatar/' . $avatar . '">' . "\n"; // PHP_EOL powinno być tu lepsze, ponieważ wykona to samo w każdym systemie
...
)

i podobne metody z htmlem.

Faktycznie <?= trans('charset') ?> nie powinno tak być.

Najszybciej co przyszło mi na myśl:

Kod
class Translation implements TranslationInterface
{
    private $translation;

    public function __construct()
    {
        $this->translation = json_encode($this->translation());
    }

    /* Language translation */
    public function trans(string $key, array $data = null, array $sprint = null): string
    {
        $trans = json_decode($this->translation, true);
    }
}


Czy ten kod rozwiązuje problem, czy można lepiej?

Pewnie tak jest, że piszę trochę z "automatu", zwykle dopiero przy drugim i kolejnym podejściu do metody zastanawiam się nad nią pod względem optymalizacji.
Tak z miejsca optymalizować kod to chyba jeszcze nie na tym poziomie, ale fajnie byłoby od razu to widzieć.

Przy okazji będąc w class Translation poprawiłem else itp. o czym wcześniej pisałeś, chociaż czy klasa jest już optymalna?
Pewnie można lepiej, ale niestety może przy trzecim podejściu zobaczę więcej i będzie super optymalnie.
nospor
Cytat
$this->translation = json_encode($this->translation());
$trans = json_decode($this->translation, true);

Czyli robisz json_encode raz, tylko po to, by potem za kazdym razem w metodzie trans petryliard razy robic json_decode. I teraz wytlumacz mi prosze, bo naprawde nie kumam, czemu nie mozesz tej tablicy przechowywac jako tablce, tylko musisz ja kodowac a potem dekodowac za kazdym razem. Jaka logika temu przyswiecala? Bo jakas na pewno musiala prawda?

Cytat
$html .= '<img class="dbm-img-profile rounded-circle" src="' . $this->path() . 'images/avatar/' . $avatar . '">' . "\n"; // PHP_EOL powinno być tu lepsze, ponieważ wykona to samo w każdym systemie

Przeciez tu generujesz kod html... tu w ogole nie trzeba nowej linii od tego zacznijmy. A nawet jesli by byla to co z tego ze serwer ci wygeneruje nowa linie wg systemu serwera, skoro klient ktory dostanie kod html moze byc na milionie innych systemow. wal \n i sobie glowy nie zawracaj

Cytat
file_put_contents($cachedFile, '<?php class_exists(\'' . __CLASS__ . '\') or exit; ?>' . PHP_EOL . $code);

To samo tutaj, to sa pliki cache, co ci zalezy czy bedzie tam \n czy PHP_EOL? TO nic nie zalatwia

Cytat
Przy okazji będąc w class Translation poprawiłem else itp. o czym wcześniej pisałeś, chociaż czy klasa jest już optymalna?

Nie wiem gdzie to poprawiles, na githubie zmian nie widze
Malinaa
Chyba spanikowałem, na szybkości dodałem json_encode() kombinując z obiektem (kolejna kombinacja pod górkę, bo logiki w tym nie widzę).
Napisałeś "dane trzymaj w obiekcie". Z tą tablicą do obiektu, aby w funkcji używać tablicy - to json_encode() wink.gif
Chyba, że chcesz, aby przerobić całą metodę trans() na obiekcie, ale to nie wiem o co chodzi kiedy dane są w tablicy (w PHP 8 widzę coś chyba tematycznego enum{})

Czy nie może być po prostu:
Kod
public function __construct()
    {
        $this->translation = $this->translation();
    }

bo nie rozumiem o co chodzi z tym obiektem z reqiure array.

Przy PHP_EOL chcę się tu zdecydować na jedno PHP_EOL lub "\n", wcześniej dadawałem "\n" bo prościej niż pisać PHP_EOL, ale to daje w każdym systemie ten sam efekt, więc czy nie lepiej użyć PHP_EOL.
Załatwia to tyle, że przy wyświetleniu źródła strony jest czytelnie, a bez przejść do nowej linii mamy wszystko w jednej niekończącej się linii (za górami, za lasami... nie może tak być).

Nie było jeszcze kiedy poprawiać szablony pod nowy silnik, ale kilka poprawek przy silniku wczoraj przesłałem TemplateFeauture i Translation
https://github.com/artimman/dbmframework/tr...ication/classes
nospor
Cytat
Napisałeś "dane trzymaj w obiekcie".

Chodzilo mi o obiekt translation, ze w nim masz trzymac dane, a nie ze dane maja byc obiektem

Cytat
Przy PHP_EOL chcę się tu zdecydować na jedno PHP_EOL lub "\n", wcześniej dadawałem "\n" bo prościej niż pisać PHP_EOL, ale to daje w każdym systemie ten sam efekt, więc czy nie lepiej użyć PHP_EOL.
Załatwia to tyle, że przy wyświetleniu źródła strony jest czytelnie, a bez przejść do nowej linii mamy wszystko w jednej niekończącej się linii (za górami, za lasami... nie może tak być).

Uzywaj \n i nie kombinuj, Juz ci zdaje sie to napisalem. to nie 20 lat temu ze trzeba bylo sie takimi duperami przejmowac bo kazdy system wszystko inaczej interpretowal. Teraz nowa linia to uniwersalne \n
Malinaa
Przy sprzątaniu i optymalizacji natrafiłem na kod w public/index.php który był z wersji v1

isset($_GET['url']) ? $fileBasename = basename(str_replace('/', ',', $_GET['url']), '.html') : $fileBasename = 'index';
...
define('BASE_FILE', $fileBasename);

W obecnej wersji nie ma już $_GET['url'] a BASE_FILE jest używane tylko w jednym miejscu, więc nie ma potrzeby definiować.

W pliku start.php -> function reportingErrorHandler() dopisałem

Kod
$basename = 'index';
    $uri = $_SERVER["REQUEST_URI"];
    $dir = str_replace('public', '', dirname($_SERVER['PHP_SELF']));

    if ($uri !== $dir) {
        $basename = str_replace('.html', '', basename($_SERVER["REQUEST_URI"]));

        if (strpos($uri, '.') !== false) {
            preg_match('/\.(.*?)\./', $uri, $match);

            if (array_key_exists(1, $match)) {
                $basename = $match[1];
            }
        }
    }


i powyższe posprzątane, ale wyszło sporo zagnieżdżeń.

1. Szukam pomysłu jak uprościć kod?

System rozbudowany jest o rejestracje i logowanie, Admin po zalogowaniu może przejść do Panelu.
2. W panelu sporo jest w JS, ale pisałem w jQuery i AJAX, chyba należałoby zmienić na np. React?
A jeżeli React to pewnie przydałby się Webpack. No i pytanie jak to zrobić z tym kodem JS i AJAX, aby było super dobrze wink.gif

System szablonów zrobiony i szablony przerobione pod nowy system, zaktualizowane na Gicie:
https://github.com/artimman/dbmframework
nospor
metoda trans nadal za kazdym razem gdy jest wywolywana odczytuje plik z tlumaczeniami.
Malinaa
Metoda trans() w którym pliku/klasie?

W class Translation został dopisany konstruktor i wygląda Ok

public function __construct()
{
$this->translation = $this->translation();
}

Patrzę do class TemplateFeature - tutaj jest nie zmienione, ale sytuacja się komplikuje, ponieważ tu wszystko jest public dla szablonów
i nie wstrzyknę metod z class Translation -> private - będzie konflikt

Co zrobić, aby metod z class Translation -> translation() móc używać też w class TemplateFeature w obu klasach i nie powtarzać kodu.
Spróbowałem wstrzyknąć na różne sposoby, ale ciągle coś wyskakuje że musi być public?

Dla przykładu daję kod z metody do konstruktora
Kod
class TemplateFeature
{
    public $translation;

    public function __construct()
    {
        $cookieName = 'DbmLanguage';
        $languageDefault = 'pl';
        $arrayLanguages = explode('|', APP_LANGUAGES);

        !empty($arrayLanguages[0]) ? $language = $arrayLanguages[0] : $language = $languageDefault;

        if (!empty($_GET['lang'])) {
            $language = $_GET['lang'];

            if (strtolower($language) === 'off') {
                $language = $languageDefault;
            }
        } elseif (isset($_COOKIE[$cookieName])) {
            $language = $_COOKIE[$cookieName];
        }

        $pathTranslation = BASE_DIRECTORY . "translations/language." . strtolower($language) . ".php";

        if (file_exists($pathTranslation)) {
            $this->translation = include($pathTranslation);
        }
    }

}

...

public function trans(string $key, array $overwrite = [], array $sprint = null): string
    {
        if (!empty($this->translation)) {
            $translation = $this->translation;
            ....
        }

    }


otrzymuję komunikat:
Fatal error: Access level to App\Controller\IndexController::$translation must be public (as in class Dbm\Classes\BaseController) in IndexController.php on line 18

Nie chciałbym teraz dla tego $translation zmieniać wszystkie kontrolery private na public

Zmieniam w klasie public $translation; na public $publicTranslation; komunikat znika, oki, ale nie wczytuje tablicy if (!empty($this->publicTranslation)) jest empty, ścieżka ok itp. coś blokuje odczytanie tablicy?

- - -

Zmieniłem jednak kontrolery i parę rzeczy:
https://github.com/artimman/dbmframework/co...8979ae418856695
Metoda poprawiona - wygląda Ok? I mniej kodu w kontrolerach, czyli też Ok.
nospor
Tak, wlasnie o cos takiego mi chodzilo
public function __construct()
{
$this->arrayTranslation = $this->translation();
}




No ale czemu za kazdym razem tworzysz teraz znowu obiekt translation? Czemu nie stworzysz go raz na takiej samej zasadzie jak DataBase i nie przekazujesz gdzie trzeba?
Malinaa
Konstruktor, o który chodziło to już był.

Obiekt translation tworzę raz w class BaseController extends TemplateEngine
Nie za bardzo chciałbym tworzyć $translation w index.php i przechodzić przez całość Router itd...
Po co jechać, aż od index.php, bo chyba o tym mowa!
Czy nie może zostać w BaseController?
nospor
Cytat
Konstruktor, o który chodziło to już był.

Mi nie chodzilo o bycie konstruktora, tylko o to co w nim mialo byc...

Cytat
Obiekt translation tworzę raz w class BaseController extends TemplateEngine
Nie za bardzo chciałbym tworzyć $translation w index.php i przechodzić przez całość Router itd...
Po co jechać, aż od index.php, bo chyba o tym mowa!
Czy nie może zostać w BaseController

Obiekt tranlation tworzysz w wielu miejscach, nie tylko w BaseController. Wiec nadal wielokrotnie powielasz te same akcje, ala czytanie tego samego pliku,
I wracamy znowu dotego samego, niby chcesz porzadnie a potem i tak po lebkach robisz. Sie zdecyduj
Malinaa
Ok, rozumiem o czym mówisz, kilka tygodni temu zostało już zrobione tak jak miało być...
teraz tylko zmieniłem nazwę $this->translation = $this->translation(); na $this->arrayTranslation - to już było zrobione na to co w nim miało być.

Cytat
Obiekt tranlation tworzysz w wielu miejscach...


Faktycznie był tworzony jeszcze w modelach LoginModel i RegisterModel, poprawiłem jest już tylko w BaseController.
Czy teraz jest Ok, czy trzeba jechać od index.php? Jeśli tak to nie rozumiem, dlaczego aż od index.php .
Co w przypadku np. new PHPMailer() obiekt jest tworzony wiele razy jeśli podstrona wymaga obsługi email,
ale jak rozumiem optymalnie będzie $translation obiekt utworzyć jeden raz.
Zmiana $transloation (obiekt utworzony tylko jeden raz w BaseController):
https://github.com/artimman/dbmframework/co...b186fb927320b16

Zastanawia mnie jeszcze:
Kod
class TemplateFeature
{
    public $translation;
    ...
}
to "public", z którym był kłopot musiałem tutaj dodać
nospor
Cytat
Jeśli tak to nie rozumiem, dlaczego aż od index.php .

Ja nie sledze dokladnie twojego kodu. DataBase musialo byc od index, potem widziale mze translation tez tworzysz w kilku miejscach wiec tez wydalo sie ze ma byc od index. Generalnei chodzi o to by nie tworzyc tego samego obiektu milion razy co ci sie zdarzalo.


Cytat
Zastanawia mnie jeszcze:
Kod
class TemplateFeature
{
public $translation;
...
}
to "public", z którym był kłopot musiałem tutaj dodać

czemu nie ustawisz tego translation w construktorze popprostu?
Malinaa
Cytat
Generalnei chodzi o to by nie tworzyc tego samego obiektu milion razy co ci sie zdarzalo.

Jasne. Dzięki, że zwróciłeś na to uwagę, bo gdzieś mi się "zapodziało". 1 Milion smile.gif

class TemplateFeature jest taką trochę inną klasą "zewnętrzną" (wszystko musi być public), wszystko stąd idzie tylko w szablonach
i o dziwo ? nie ma potrzeby tworzenia konstruktora, ustawiam tylko public $translation;
i w metodzie trans() o której pisałeś że ładuje tablice za każdym razem daje
!empty($this->translation->arrayTranslation) ? $translation = $this->translation->arrayTranslation : $translation = null;
i całe to wielokrotne ładowanie tej samej tablicy mogłem usunąć (trochę dziwne, no ale działa bez błędu) i jest zoptymalizowane.

Była informacja, aby wykonać jeszcze testy w PHPUnit najlepiej TDD.

Tworzę class DatabaseTest {} i chciałbym przetestować połączenie i metody klasy Database w application/classes/.
szukam informacji w Necie, próbuję napisać test, ale nic sensownego nie wychodzi.
Jak napisać testy jednostkowe TDD z PHPUnit?
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.