Kleine Updates aus den Kommentaren, vielen dank dafür. - Der Router aus dem Video funktioniert nicht im Document Root, das habe ich nachträglich im Code gefixt - Die Callables am Ende waren falsch, das habe ich nachträglich gefixt Eventuelle Bugs werden hier aktualisiert, sorry dafür
@@pinkeHelga ich habe mir Gedanken gemacht und ich wollte gerne if statements und preg_replace etc vermeiden. Ich habe was ganz Banales gemacht github.com/BlackScorp/php-router/blob/master/Request.php#L16-L19 einfach an die Strings vorne eine Raute angehängt und somit wird nur der Part am Anfang im BaseDir entfernt und nicht irgendwo zwischendurch
Hi Vitalij, schön das es wieder ein neues Video gibt. Thema finde ich total interessant weil ich mich vor paar Wochen erst damit auseinander gesetzt habe.
@@VitalijMik Aus Zeitgründen habe ich mich für was fertiges entschieden mit dem steampixel/simple-php-router. Hätte zwar gerne selber versucht, aber die Zeit fehlt dann doch alles selber zu machen
Ja das ist eh die bessere Wahl, das habe ich auch im video so gesagt, die Packages sind alle gut durchgetestet und wenn irgendwas auffällt kann man den Fehler reporten. Der eigene Router wird früher oder später an seine Grenzen kommen
Moin Vitalij, sehr mächtig! Da muss ich erst einmal durchsteigen, das wird mit Sicherheit eine Weile dauern, doch dank deines Videos kann man sich auch solch verhältnismäßig komplizierte Themen annehmen und sie sukzessive lernen. Ich benutze bereits deinen älteren Router "BlackScorp\Funci", der seinen Soll auch sehr gut erfüllt, doch scheint diese Variante sich noch mehr an einem Framework Router zu orientieren. Danke dafür!
korrekt, funci war halt ein einstieg mit funktionen, das hier ist die OOP Variante davon. Ein Framework Router kann aber noch einiges mehr. Ich bin mir sicher dass irgendwelche Spezielle URLs nicht einfach so funktionieren. Bei einem Framework router haben aber viele Entwickler drauf geschaut in vielen Projekten und man sagt ja nicht umsonst dass vier Augen mehr sehen als zwei ;)
Danke für Deine vielen Videos. Das hat mich wirklich weiter gebracht! Ich habe eine Frage zu Deinem Router. Gibt es eine Möglichkeit die Variablen in den Routen optional zu machen?
Dankeschön, Composer selbst hat kein Router, es gibt aber fertige Router die man via Composer installieren kann. Der Unterschied zu meinem Router und denen die es online gibt ist einfach nur der dass diese Besser umgesetzt sind (aus Architektonischer Sicht) und für viele Fälle durchgetestet sind da es von vielen benutzt wird. Mein Router ist nur eine sehr vereinfachte Version um das Grundprinzip zu verstehen.
Hi, du sagst in Minute 27:10 (nur damit es findest 🙂) ...das man mit /? im regex pattern optional ein Slash angeben kann damit er trotzdem die ID liesst..... /profile/222/ oder /profile/22 ..... funktioniert auch, nur liesst er bei mir alles was danach kommt als ID, wenn ich angebe /profile/222/test/test , dann ist die ID: 222/test/test statt nur ID: 222 Ich würde das gerne auch für Subrouten nutzen /user/{id}/list/ Wie kann ich das Subrouting, dann steuern 🙂
Interessantes Video.. 👍 Was mich interessiert, obwohl in der Router Klasse, die register Methode einen Closure bzw. callable verlangt, du ein Array übergibst und dennoch der Controller aufgerufen wird. 🙃 Der Part funktioniert bei mir nicht, hab ich da was verpasst? ;)
Dankeschön. also den Funktionierenden Code siehst du unten in der Videbeschreibung. ALlerdings sind ja mittlerweile so einige PHP Versionen rausgekommen, ich meine ich habe das Video mit PHP 7.4 umgesetzt. Kann sein dass es mit den neusten Version nicht funktioniert. Kann auch sein dass ich da ein bug habe. Wenn du ein Fehler hast dann lasse es mich wissen wie man den nachstellt mit dem Code aus der Beschreibung und dann fixe ich den.
@@VitalijMik Dein Code im git nutzt die Variante über Invoke $router->register('/profile/{id}', new ProfileController(),'POST'); Im Video hattest du auch die Variante über die IndexAction, diese funktioniert bei mir in 7.4 und ab 8 nicht, da er ein Closure erwartet und kein Array. $router->register('/profile/{id}', [ IndexController::class, ' IndexAction'] ); An der Stelle wunderte es mich das es bei dir geht 😊
Hi Vitalij, I like your tutorial and implemented it in my project. Now I want to register a route with a specific URL and the same URL with a different method (e.g. /user/{id} with GET and /user/{id} with POST ) should use different controller functions. How can I do this, because in routes the key of the routes array is only the url.
Assuming your Profile Controller have a saveAction and a viewAction as Method $profileController = new ProfileController(); $router->register('/user/{id}',[$profileController,'saveAction'],'POST'); $router->register('/user/{id}',[$profileController,'viewAction'],'GET');
@@VitalijMik the problem here is that the route in my routes-Array is overwritten from the second registered route, because the array key was only the url. I could solve this by changing the register function of the Router to add a key which contains also the method: if($methods == 'GET|POST') { $this->routes[$url.'_GET']= [ 'action' => $action, 'methods' => $methods ]; $this->routes[$url.'_POST']= [ 'action' => $action, 'methods' => $methods ]; } else { $this->routes[$url.'_'.$methods]= [ 'action' => $action, 'methods' => $methods ]; } and in the handle function I changed the searchString to the following, because my routeKey contains now the method as well: $searchString = $request->getUrl().'_'.$request->getMethod() . self::SEPARATOR .$request->getMethod(); Now I can register those routes (first shows the empty login page, second handles the input with the post parameters in the Controller.): $router->register('/login',function(REQUEST $request){ return require_once('views/login.php'); },'GET'); $router->register('/login',function(REQUEST $request){ return Controller::loginAction($request); },'POST'); I know that this is not very smart, but solved temporary my problem.
@@ChristianBohm-hp3kb actually it should work github.com/BlackScorp/php-router/blob/master/Router.php#L10 the URL is here a regular expression not just the URL. your if statement is not required there
@@VitalijMik this regEx handles only the parameters like {id},.. within the url ( e.g. student/{id} and not the method. My urls just differ from the method. I need the if in the register to add two sets of "routes with method" because when i handle the request, there is only one of the methods left, so I add two for GET|POST.
@@maxmuster3229 ja klar, ich nutze ja auch symfony, hier ging es nur um grob und sehr vereinfacht zu erklären wie ein router funktionieren könnte. am ende landet man sowieso bei einem framework was das mit sich bringt und dann auch noch besser über attributes :D
@@VitalijMik :: ist der "Gültigkeitsoperator". Auf englisch "scope resolution operator" und er hat eine dedizierte Bedeutung und Funktion. Man sollte ihn nicht als Separator benutzen. Anfänger könnten dadurch verwirrt werden. Fortgeschrittene könnten die Augenbrauen hochziehen :-))
@@maxmuster3229 schon, hier gehts aber einfach nur darum dass HTTP method vom regex getrennt ist, ich habe halt einfach irgend eine zeichenfolge genommen. zum glück ist es in einer konstante und man kann es eben anpassen.
41:10 Wieso nimmst Du da INPUT_POST in der Methode get()? Eigentlich geht da ja alles um den Query. Vielleicht besser eine Methode getParamGetPost() nachschalten? Besser ist sowieso, auf htaccess zu verzichten und alles in der Serverkonfiguration zu setzen. Wenn man absolute Pfade in der Serverkonfiguration tolerieren kann, tut's beim Apache auch die ErrorDocument-Direktive.
Beim Nginx wundert mich, daß man erst eine benutzerdefinierte Variable mit set kopieren muß. Die interne Variable übergibt er aus irgend welchen Gründen nicht per fastcgi_param. Weißt Du vielleicht wieso?
das musst du erläutern, ich habe das im DOCUMENT_ROOT getestet und da hat alles funktioniert, die htaccess aus dem video ist ein Teil der Symfony htaccess. Deine RewriteRule macht das selbe wie die aus dem Video. Und wieso Performancebremse? Im vergleich zu was? ;) nginx ?
also das mit INPUT_POST das ist eine Anspielung an Frameworks, in einem Framework ist es auch so dass du einen Request im Controller bekommst und der hat die Methode get, diese wiederum prüft erst QueryString ab, dann post variablen, dann session und zum schluss noch env variablen. Wahrscheinlich wäre es da besser wenn ich mich an das PSR-7 Message interface gehalten hätte, da gibts die methode getParsedBody und getQueryParams Wieso ist es besser auf eine .htaccess zu verzichten? Der Code sollte letzendlich flexibel unabhängig von der Serverconfig funktionieren. Ich denke es gibt nichts schlimmeres als wenn man eine Datei auf einen anderen Server umzieht und man muss dann noch den Server anpassen.
Kleine Updates aus den Kommentaren, vielen dank dafür.
- Der Router aus dem Video funktioniert nicht im Document Root, das habe ich nachträglich im Code gefixt
- Die Callables am Ende waren falsch, das habe ich nachträglich gefixt
Eventuelle Bugs werden hier aktualisiert, sorry dafür
Kein Ding! Dazu diskutieren wir ja Code Review ;-)
Beim eigenen Code hat man Tomaten auf den Augen.
@@pinkeHelga ich habe mir Gedanken gemacht und ich wollte gerne if statements und preg_replace etc vermeiden. Ich habe was ganz Banales gemacht
github.com/BlackScorp/php-router/blob/master/Request.php#L16-L19
einfach an die Strings vorne eine Raute angehängt und somit wird nur der Part am Anfang im BaseDir entfernt und nicht irgendwo zwischendurch
Großartig! Gerne mehr Videos zum erstellen eines Frameworks :)
dankeschön, war auch so geplant ;)
Hi Vitalij, schön das es wieder ein neues Video gibt. Thema finde ich total interessant weil ich mich vor paar Wochen erst damit auseinander gesetzt habe.
Dankeschön. Und hattest du eine ähnliche Umsetzung? oder hattest du das komplett anders gelöst?
@@VitalijMik Aus Zeitgründen habe ich mich für was fertiges entschieden mit dem steampixel/simple-php-router. Hätte zwar gerne selber versucht, aber die Zeit fehlt dann doch alles selber zu machen
Ja das ist eh die bessere Wahl, das habe ich auch im video so gesagt, die Packages sind alle gut durchgetestet und wenn irgendwas auffällt kann man den Fehler reporten. Der eigene Router wird früher oder später an seine Grenzen kommen
Moin Vitalij, sehr mächtig! Da muss ich erst einmal durchsteigen, das wird mit Sicherheit eine Weile dauern, doch dank deines Videos kann man sich auch solch verhältnismäßig komplizierte Themen annehmen und sie sukzessive lernen. Ich benutze bereits deinen älteren Router "BlackScorp\Funci", der seinen Soll auch sehr gut erfüllt, doch scheint diese Variante sich noch mehr an einem Framework Router zu orientieren. Danke dafür!
korrekt, funci war halt ein einstieg mit funktionen, das hier ist die OOP Variante davon. Ein Framework Router kann aber noch einiges mehr. Ich bin mir sicher dass irgendwelche Spezielle URLs nicht einfach so funktionieren. Bei einem Framework router haben aber viele Entwickler drauf geschaut in vielen Projekten und man sagt ja nicht umsonst dass vier Augen mehr sehen als zwei ;)
Tolles Video. War sehr interessant, auch als Erfahrender Programmierer. :)
Dankeschön
Geil, Vitalij du bist ja wieder/noch da!! Ich dachte du hattest UA-cam den Rücken gekehrt aufgrund der sinnlosen Mecker- und Hate-kommentare 😳
Ich sagte im Video nur dass ich das ganze mehr wie ein Hobby behandle und dann videos erstelle, wie ich gerade Lust/Zeit habe
@@VitalijMik ok. Ist schon 'ne weile her. Aber gut dass du weiter machst! 🤘🏻🤘🏻🤘🏻🤘🏻😎🙏🏻
Du bist unglaublich...!!!!
Dankeschön, viel spaß mit dem Video :D
Sehr cool. Vielen Dank.
Danke fürs Zuschauen und kommentieren
Wie immer gut erklärt, DANKE!
dankeschön
Sehr cool, danke dir 👍
danke dir fürs komentieren ;)
Great Tutu
We waiting anothor tuto how to group routes and prefix it and name it 😍
Great idea. Will think about it
Super 🎉
Danke
geliked 🙂
Dankeschön
Danke für Deine vielen Videos. Das hat mich wirklich weiter gebracht! Ich habe eine Frage zu Deinem Router. Gibt es eine Möglichkeit die Variablen in den Routen optional zu machen?
die sind eigentlich optional, wenn du keine angibst, sollte es auch ohne gehen
Genau das, was ich brauche. Danke!
Wo ist der Unterschied zwischen deinem und einem Composer Router?
Dankeschön,
Composer selbst hat kein Router, es gibt aber fertige Router die man via Composer installieren kann.
Der Unterschied zu meinem Router und denen die es online gibt ist einfach nur der dass diese Besser umgesetzt sind (aus Architektonischer Sicht) und für viele Fälle durchgetestet sind da es von vielen benutzt wird. Mein Router ist nur eine sehr vereinfachte Version um das Grundprinzip zu verstehen.
Hi, du sagst in Minute 27:10 (nur damit es findest 🙂) ...das man mit /? im regex pattern optional ein Slash angeben kann damit er trotzdem die ID liesst..... /profile/222/ oder /profile/22 ..... funktioniert auch, nur liesst er bei mir alles was danach kommt als ID, wenn ich angebe /profile/222/test/test , dann ist die ID: 222/test/test statt nur ID: 222
Ich würde das gerne auch für Subrouten nutzen /user/{id}/list/
Wie kann ich das Subrouting, dann steuern 🙂
ah das ist ein Bug .
$url = preg_replace('~{(.*)}~mU', '(?\S+)', $url);
in diesem Regex wenn du statt \S+ ein \w+ schreibst, sollte es funktionieren
Interessantes Video.. 👍
Was mich interessiert, obwohl in der Router Klasse, die register Methode einen Closure bzw. callable verlangt, du ein Array übergibst und dennoch der Controller aufgerufen wird. 🙃
Der Part funktioniert bei mir nicht, hab ich da was verpasst? ;)
Dankeschön.
also den Funktionierenden Code siehst du unten in der Videbeschreibung. ALlerdings sind ja mittlerweile so einige PHP Versionen rausgekommen, ich meine ich habe das Video mit PHP 7.4 umgesetzt. Kann sein dass es mit den neusten Version nicht funktioniert.
Kann auch sein dass ich da ein bug habe. Wenn du ein Fehler hast dann lasse es mich wissen wie man den nachstellt mit dem Code aus der Beschreibung und dann fixe ich den.
@@VitalijMik Dein Code im git nutzt die Variante über Invoke
$router->register('/profile/{id}', new ProfileController(),'POST');
Im Video hattest du auch die Variante über die IndexAction, diese funktioniert bei mir in 7.4 und ab 8 nicht, da er ein Closure erwartet und kein Array.
$router->register('/profile/{id}', [ IndexController::class, ' IndexAction'] );
An der Stelle wunderte es mich das es bei dir geht 😊
als ich das video gedreht habe, habe ich noch 7.4 benutzt
Hi Vitalij, I like your tutorial and implemented it in my project. Now I want to register a route with a specific URL and the same URL with a different method (e.g. /user/{id} with GET and /user/{id} with POST ) should use different controller functions. How can I do this, because in routes the key of the routes array is only the url.
Assuming your Profile Controller have a saveAction and a viewAction as Method
$profileController = new ProfileController();
$router->register('/user/{id}',[$profileController,'saveAction'],'POST');
$router->register('/user/{id}',[$profileController,'viewAction'],'GET');
@@VitalijMik the problem here is that the route in my routes-Array is overwritten from the second registered route, because the array key was only the url. I could solve this by changing the register function of the Router to add a key which contains also the method:
if($methods == 'GET|POST') {
$this->routes[$url.'_GET']= [
'action' => $action,
'methods' => $methods
];
$this->routes[$url.'_POST']= [
'action' => $action,
'methods' => $methods
];
} else {
$this->routes[$url.'_'.$methods]= [
'action' => $action,
'methods' => $methods
];
}
and in the handle function I changed the searchString to the following, because my routeKey contains now the method as well:
$searchString = $request->getUrl().'_'.$request->getMethod() . self::SEPARATOR .$request->getMethod();
Now I can register those routes (first shows the empty login page, second handles the input with the post parameters in the Controller.):
$router->register('/login',function(REQUEST $request){
return require_once('views/login.php');
},'GET');
$router->register('/login',function(REQUEST $request){
return Controller::loginAction($request);
},'POST');
I know that this is not very smart, but solved temporary my problem.
@@ChristianBohm-hp3kb actually it should work
github.com/BlackScorp/php-router/blob/master/Router.php#L10
the URL is here a regular expression not just the URL. your if statement is not required there
@@VitalijMik this regEx handles only the parameters like {id},.. within the url ( e.g. student/{id} and not the method. My urls just differ from the method. I need the if in the register to add two sets of "routes with method" because when i handle the request, there is only one of the methods left, so I add two for GET|POST.
@@ChristianBohm-hp3kb check the video description there is the link to the source code, iam pretty sure it works with third parameter
Welchen Router nutzt ihr in euren Projekten?
Sieht interessant aus, danke
Den von laminas :)
steampixel/simple-php-router, aber erst seit ein paar Wochen
früher habe ich das einfach direkt aus htaccess gemacht, heute viel mit Symfony, weil einfacher
@@maxmuster3229 ja klar, ich nutze ja auch symfony, hier ging es nur um grob und sehr vereinfacht zu erklären wie ein router funktionieren könnte. am ende landet man sowieso bei einem framework was das mit sich bringt und dann auch noch besser über attributes :D
Das mit dem Separator :: ist sehr übel. Kinder, bitte, sowas nicht zu Hause nachmachen.
Gerne mehr details, vielleicht übersehe ich ja irgendwas ;)
@@VitalijMik :: ist der "Gültigkeitsoperator". Auf englisch "scope resolution operator" und er hat eine dedizierte Bedeutung und Funktion. Man sollte ihn nicht als Separator benutzen. Anfänger könnten dadurch verwirrt werden. Fortgeschrittene könnten die Augenbrauen hochziehen :-))
@@maxmuster3229 schon, hier gehts aber einfach nur darum dass HTTP method vom regex getrennt ist, ich habe halt einfach irgend eine zeichenfolge genommen. zum glück ist es in einer konstante und man kann es eben anpassen.
Ich kann hier nix mehr kommentieren. Wird immer sofort gelöscht. :/
41:10 Wieso nimmst Du da INPUT_POST in der Methode get()? Eigentlich geht da ja alles um den Query. Vielleicht besser eine Methode getParamGetPost() nachschalten?
Besser ist sowieso, auf htaccess zu verzichten und alles in der Serverkonfiguration zu setzen. Wenn man absolute Pfade in der Serverkonfiguration tolerieren kann, tut's beim Apache auch die ErrorDocument-Direktive.
Ich hoffe, das bleibt jetzt mal alles stehen. Schwierig, alles durch die Filter zu bringen. oO
Beim Nginx wundert mich, daß man erst eine benutzerdefinierte Variable mit set kopieren muß. Die interne Variable übergibt er aus irgend welchen Gründen nicht per fastcgi_param. Weißt Du vielleicht wieso?
das musst du erläutern,
ich habe das im DOCUMENT_ROOT getestet und da hat alles funktioniert, die htaccess aus dem video ist ein Teil der Symfony htaccess. Deine RewriteRule macht das selbe wie die aus dem Video. Und wieso Performancebremse? Im vergleich zu was? ;) nginx ?
also das mit INPUT_POST das ist eine Anspielung an Frameworks, in einem Framework ist es auch so dass du einen Request im Controller bekommst und der hat die Methode get, diese wiederum prüft erst QueryString ab, dann post variablen, dann session und zum schluss noch env variablen. Wahrscheinlich wäre es da besser wenn ich mich an das PSR-7 Message interface gehalten hätte, da gibts die methode getParsedBody und getQueryParams
Wieso ist es besser auf eine .htaccess zu verzichten? Der Code sollte letzendlich flexibel unabhängig von der Serverconfig funktionieren. Ich denke es gibt nichts schlimmeres als wenn man eine Datei auf einen anderen Server umzieht und man muss dann noch den Server anpassen.