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

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

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ą

Jak zaczniesz pisać to tak jak na 2024 rok przystało wtedy bardzo chętnie zrobię Ci Review kodu

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)
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
$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

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 
Prosze tutaj obsługa routingu(żeby nie było że nie chcę pomoc)
Klasa Router
class Router
{
protected $routes = [];
private $database;
public function __construct(Database $database)
{
$this->database = $database;
}
public function addRoute
(string
$route, array $arrayController): void
{
$arrayControllerAction = $this->changeArrayKey($arrayController, ['controller', 'method']);
$this->routes[$route] = $arrayControllerAction;
}
public function dispatch(string $uri): void
{
$database = $this->database;
$uri = $this->matchLocalhost($uri);
$route = $this->matchRoute($uri);
$uri = $route['uri'];
$hasParams = false;
if (!empty($route['params'])) { $hasParams = true;
$uri = $this->buildRouteUri($route['paths'], $route['params']);
}
$controller = $this->routes[$uri]['controller'];
$method = $this->routes[$uri]['method'];
if (class_exists($controller)) {
$controllerInstance = new $controller($database);
if (method_exists($controllerInstance, $method)) {
if ($hasParams) {
$controllerInstance->$method((int
)end($route['params'])); } else {
$controllerInstance->$method();
}
} else {
throw new ExceptionHandler("No method $method on class $controller!", 500);
}
} else {
throw new ExceptionHandler("No controller $controller!", 500);
}
} else {
throw new ExceptionHandler("Route not found! addRoute('$uri')", 404);
}
}
{
foreach ($array as $key => $value) {
$newArray[$keys[$key]] = $value;
}
return $newArray;
}
private function matchLocalhost(string $uri): ?string
{
$haystack = APP_PATH;
$needle = 'localhost';
if (strpos($haystack, $needle) !== false) {
}
return null;
}
private function buildRouteUri
(array $paths, array $params): string
{
$params[0] = '{#}';
$params[count($params) - 1] = '{id}'; }
private function matchRoute
(string
$uri): array {
$path = filter_var($uri, FILTER_SANITIZE_URL);
$path = ltrim($path, '/');
if (($pos = strpos($uri, '?')) !== false) { }
$paths = [];
$params = [];
foreach ($path as $subPath) {
if (strpos($subPath, '.html') !== false) { if (($pos = strpos($param, '.html')) !== false) { }
} else {
$paths[] = $subPath;
}
}
/*if (strpos($uri, ',') !== false) {
$uri = substr($uri, 0, 1) . substr($uri, strpos($uri, ',') + 1);
}*/
/* $parts = explode(',', $uri);
$uri = '/' . array_pop($parts); */
foreach($path as $index => $param){
$indexNum[] = $index;
}
}
//print_r($indexNum);
/*if ((strpos($uri, '-')) !== false) {
//$parts = explode('/', $uri);
//$last = array_pop($parts);
//echo ' | '. $last;
$link = str_replace(['/', '.html'], '', $uri);
$segments = explode(',', str_replace('/', '', $link));
foreach ($segments as $key => $value) {
if (is_numeric($value)) {
$segments[$key] = '{$}';
}
if ((strpos($value, '-')) !== false) {
$segments[$key] = '{#}';
}
}
//$uri = '/' . $path[0] . '/' . implode(',', $segments) . '.html';
$uri = '/' . implode(',', $segments) . '.html';
//echo $uri;
}*/
return [
'uri' => $uri,
'paths' => $paths,
'params' => $params
];
}
/* private function requestMethod() : string
{
return $_SERVER['REQUEST_METHOD'];
}
private function requestPath(): string
{
return parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
} */
}
Plik routes.php
return function (Database $database) {
$uri = $_SERVER['REQUEST_URI'];
$router = new Router($database);
$router->addRoute('/', [IndexController::class, 'index']);
$router->addRoute('/link.html', [IndexController::class, 'linkMethod']);
$router->addRoute('/home.html', [HomeController::class, 'index']);
$router->addRoute('/about.html', [AboutController::class, 'index']);
$router->addRoute('/contact.html', [ContactController::class, 'index']);
$router->addRoute('/regulation.html', [RegulationController::class, 'index']);
$router->addRoute('/page', [PageController::class, 'index']);
$router->addRoute('/page/site', [PageController::class, 'siteMethod']); // ? /page/site.html
$router->addRoute('/site.html', [PageController::class, 'siteMethod']); // ?
$router->addRoute('/offer.html', [PageController::class, 'offerMethod']); // /{#},offer.html
$router->addRoute('/blog', [BlogController::class, 'index']);
$router->addRoute('/blog/sections', [BlogController::class, 'sectionsMethod']);
$router->addRoute('/blog/{#},sec,{id}.html', [BlogController::class, 'sectionMethod']);
$router->addRoute('/blog/{#},art,{id}.html', [BlogController::class, 'articleMethod']);
$router->dispatch($uri);
};
W pliku routes musiałem poprawić route dla artykułow bo pattern się nie zgadzał z regułami rewrite oraz linkami na stronie
private function buildRouteUri
(array $paths, array $params): string
{
$params[0] = '{#}';
$params[count($params) - 1] = '{id}'; }
$paths = '/'.implode('/', $paths). '/'; } else {
$paths = '/';
}
return $paths . implode(',', $params).'.html'; }
Mała zamiana do obsługi stron typu the-best-offer,offer.html
private function matchRoute
(string
$uri): array {
$path = filter_var($uri, FILTER_SANITIZE_URL);
$path = ltrim($path, '/');
if (($pos = strpos($uri, '?')) !== false) { }
$paths = [];
$params = [];
foreach ($path as $subPath) {
if (strpos($subPath, '.html') !== false) { if (end($params) === $subPath) { $params = [];
break;
}
if (($pos = strpos($param, '.html')) !== false) { }
} else {
$paths[] = $subPath;
}
}
/*if (strpos($uri, ',') !== false) {
$uri = substr($uri, 0, 1) . substr($uri, strpos($uri, ',') + 1);
}*/
/* $parts = explode(',', $uri);
$uri = '/' . array_pop($parts); */
foreach($path as $index => $param){
$indexNum[] = $index;
}
}
//print_r($indexNum);
/*if ((strpos($uri, '-')) !== false) {
//$parts = explode('/', $uri);
//$last = array_pop($parts);
//echo ' | '. $last;
$link = str_replace(['/', '.html'], '', $uri);
$segments = explode(',', str_replace('/', '', $link));
foreach ($segments as $key => $value) {
if (is_numeric($value)) {
$segments[$key] = '{$}';
}
if ((strpos($value, '-')) !== false) {
$segments[$key] = '{#}';
}
}
//$uri = '/' . $path[0] . '/' . implode(',', $segments) . '.html';
$uri = '/' . implode(',', $segments) . '.html';
//echo $uri;
}*/
return [
'uri' => $uri,
'paths' => $paths,
'params' => $params
];
}
oraz matchRoute by nie łapało niepotrzebnie /link.html jako pattern /{#}.html wtedy kiedy nie powinno

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

ale jak tak ma być jak masz to wtedy jeszcze taka zmiana
private function buildRouteUri
(array $paths, array $params): string
{
if (count($params) > 2
) { $params[0] = '{#}';
}
$params[count($params) - 1] = '{id}'; }
$paths = '/'.implode('/', $paths). '/'; } else {
$paths = '/';
}
return $paths . implode(',', $params).'.html'; }
i w routes.php
return function (Database $database) {
$uri = $_SERVER['REQUEST_URI'];
$router = new Router($database);
$router->addRoute('/', [IndexController::class, 'index']);
$router->addRoute('/link.html', [IndexController::class, 'linkMethod']);
$router->addRoute('/home.html', [HomeController::class, 'index']);
$router->addRoute('/about.html', [AboutController::class, 'index']);
$router->addRoute('/contact.html', [ContactController::class, 'index']);
$router->addRoute('/regulation.html', [RegulationController::class, 'index']);
$router->addRoute('/page', [PageController::class, 'index']);
$router->addRoute('/page/site', [PageController::class, 'siteMethod']); // ? /page/site.html
$router->addRoute('/site.html', [PageController::class, 'siteMethod']); // ?
$router->addRoute('/offer.html', [PageController::class, 'offerMethod']); // /{#},offer.html
$router->addRoute('/{#},offer.html', [PageController::class, 'offerMethod']); // /{#},offer.html
$router->addRoute('/blog', [BlogController::class, 'index']);
$router->addRoute('/blog/sections', [BlogController::class, 'sectionsMethod']);
$router->addRoute('/blog/{#},sec,{id}.html', [BlogController::class, 'sectionMethod']);
$router->addRoute('/blog/{#},art,{id}.html', [BlogController::class, 'articleMethod']);
$router->addRoute('/{#},sec,{id}.html', [BlogController::class, 'sectionMethod']);
$router->addRoute('/{#},art,{id}.html', [BlogController::class, 'articleMethod']);
$router->addRoute('/user,{id}.html', [UserController::class, 'index']);
$router->dispatch($uri);
};
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:
$router->addRoute('/blog/{#},sec,{id}.html', [BlogController::class, 'sectionMethod']);
$router->addRoute('/blog/{#},art,{id}.html', [BlogController::class, 'articleMethod']);
$router->addRoute('/{#},sec,{id}.html', [BlogController::class, 'sectionMethod']);
$router->addRoute('/{#},art,{id}.html', [BlogController::class, 'articleMethod']);
Jeszcze małą zmiana by każdy pattern był obsługiwany
private function buildRouteUri
(array $paths, array $params): string
{
$paramsLength = count($params); if (!is_numeric($params[0
]) && $paramsLength > 2) { // pattern /{#},sec,{id}.html itp $params[0] = '{#}';
}
$params[0] = '{#}';
}
$params[$paramsLength - 1] = '{id}';
}
$paths = '/'.implode('/', $paths). '/'; } else {
$paths = '/';
}
return $paths . implode(',', $params) . '.html'; }
oraz dispatch dla pn takiej reguły
$router->addRoute('/your-website-title,site.html', [PageController::class, 'siteMethod']);
public function dispatch(string $uri): void
{
$database = $this->database;
//$uri = $this->matchLocalhost($uri);
$route = $this->matchRoute($uri);
$uri = $route['uri'];
$hasParams = false;
if (!empty($route['params'])) { $hasParams = true;
$uri = $this->buildRouteUri($route['paths'], $route['params']);
}
}
$controller = $this->routes[$uri]['controller'];
$method = $this->routes[$uri]['method'];
if (class_exists($controller)) {
$controllerInstance = new $controller($database);
if (method_exists($controllerInstance, $method)) {
if ($hasParams) {
$controllerInstance->$method((int
)end($route['params'])); } else {
$controllerInstance->$method();
}
} else {
throw new ExceptionHandler("No method $method on class $controller!", 500);
}
} else {
throw new ExceptionHandler("No controller $controller!", 500);
}
} else {
throw new ExceptionHandler("Route not found! addRoute('$uri')", 404);
}
}