steampixel / simplePHPRouter

This is a simple and small single class PHP router that can handel the whole url routing for your project.
MIT License
406 stars 117 forks source link

Not really a problem but a question #27

Closed Nex4T closed 4 years ago

Nex4T commented 4 years ago

if i have a route like this Route::add('member/([0-9]*)', function($v) { include('member.php'); }, ['get','post']); i cant use var $v in member.php, how can i use it there?

steampixel commented 4 years ago

Lol^^ My auto-responder sends automatic answers to github ^^ The Variable $v should be available inside member.php because its the same scope. Just do not define it in member.php! Just use it.

Nex4T commented 4 years ago

Hab ich versucht aber kein wert wird übermittelt

Nex4T commented 4 years ago

die variable v ist dann leer

steampixel commented 4 years ago

kannst du die variable denn vor dem include ausgeben?

Nex4T commented 4 years ago

ja vor dem include klappt es aber ich würde diese gerne der datei übergeben, ansonsten muss ich immer mit ?id=1 oder session arbeiten..

btinet commented 4 years ago

Ich hatte da mal ein MVC basierend auf diesem Router und dem damaligen Simple MVC entworfen. Damit lassen sich GET und POST bequem an die aufzurufende Methode des jeweiligen Controllers übergeben. Bei Bedarf suche ich mal das Projekt raus.

steampixel commented 4 years ago

Seltsam. Include tut nichts anderes, als den Code dort rein zu pasten. Sicher, dass du die Variable nicht innerhalb einer Klasse oder Funktion verwendest? Dann musst du sie erst mit Global verfügbar machen. Ansonsten versuche mal diese ähnlich wie in der Antwort oben in ein superglobales Array zu kopieren: _GET['var'] = $var; Und dann nimmst du in deiner Include den Wert aus _GET.

steampixel commented 4 years ago

Es muss natürlich $_GET heißen.

Nex4T commented 4 years ago

asooo ich hab nur $id=$v aufgerufen, ich versuch es mal mit get^^

steampixel commented 4 years ago

ja das muss aber trotzdem gehen. Das hat auch nix mit dem Router zu tun denke ich. mach dir doch mal ein testfile und Include darin ein anderes testfile. dann setze in dem patent file eine variable. die sollte dann im child file enthalten sein.

Nex4T commented 4 years ago

klappt aber auch nicht habe die route http://127.0.0.1/app/test/1 Route::add('/app/test/([0-9]*)', function($v) { include('test.php'); }, ['get','post']);

innerhalb der test.php

$v = $_GET['v']; echo 'Hallo Variable '.$v;

und auch wie du geschrieben hattest folgendes probiert $_GET['v'] = $v;

ghost commented 4 years ago

if you want to pass an external variable into the function() {}, you can do this: Route::add('/app/test/([0-9]*)', function($v) use ($external) { echo $external; include('test.php'); }, ['get','post']);

Nex4T commented 4 years ago

so i can use it in test.php?

ghost commented 4 years ago

Before doing any includes and anything, try echoing the variables... you'll see what passes and what's not.

$_GET & $_POST doesn't have to be passed on, it's in the Global scope by definition. If you want to pass a $v variable that is in your route script PHP page, then you can use what I've said earlier. it is working, i often use this way to pass global config and extra variables that doesn't come from the query from route:add() path.

Nex4T commented 4 years ago

dont work by me

ghost commented 4 years ago

what doesn't work? try this to debug yourself: Route::add('/app/test/([0-9]*)', function($v) { echo "this value is: ".$v."<br>"; }, ['get','post']);

steampixel commented 4 years ago

OK. I think this is a confusing topic. I have found this: https://stackoverflow.com/questions/4675932/passing-a-variable-from-one-php-include-file-to-another-global-vs-not The guys there are also confused. Please try to global $var; inside your member.php. If this should work please report your PHP Version and a copy of your PHP.ini. Maybe some PHP Versions or configurations cannot access variables inside includes that was defined in other includes without global them.

steampixel commented 4 years ago

here is the same Problem again. https://stackoverflow.com/questions/30346991/variable-not-accessible-in-included-php-file This sounds like some kind oft a PHP bug for me.

steampixel commented 4 years ago

hi. ich kannst leider gerade nicht testen. bin noch 2 Wochen ohne Rechner unterwegs.

Nex4T commented 4 years ago

Alles gut hat keine eile, würde mich aber in Zukunft Interessieren wie man da weiter vor geht

Nex4T commented 4 years ago

Ach ich hätte zusätzlich noch eine Frage, ich würde gern ein bestimmten teil der Routen Datenbank basiert machen, sprich das du eigene Routen anlegen kannst, quasi wie ein cms wenn man eine neue Unterseite anlegen möchte, allerdings bin ich etwas ratlos wie ich da anfangen soll. Vielleicht ein Tipp für mich ?

btinet commented 4 years ago

Route host/foo/bar

Innerhalb der aufgerufenen Funktion foo dann mit der Variable bar den Content laden.

Wenn bar in der Datenbank nicht existiert entsprechend umleiten.

So würde ich es wohl machen.

Nex4T commented 4 years ago

verstehe, dachte es gibt da noch eine andere möglichkeit aber das reicht schon.

steampixel commented 4 years ago

Hi @Nex4T , zu deinem Problem: Folgendes klappt bei mir komplett ohen Probleme. Auszug aus meiner index.php:

Route::add('/member/([0-9]*)', function($v) {
  include('member.php');
}, ['get','post']);

Die Datei member.php:

<?php
echo $v;

Die URL http://localhost/test/member/7 gibt mir einfach "7" im Browser aus. Wie erwartet. Bitte schreibe mir doch nochmal, um welche PHP-Version es sich bei dir handelt. Ich habe bei mir gerade PHP 7.2 laufen.

steampixel commented 4 years ago

@Nex4T Zu deiner Datenbank-Frage:

Du hast generell einige verschiedene Möglichkeiten:

  1. Nutze statische Ruten, wo sie gebraucht werden. Zum Beispiel legst du ja routen wie /login oder /admin nicht in die Datenbank, weil die ja immer gleich sind.

  2. Nutze komplett dynamische Routen aus der Datenbank. Angenommen du hast eine Tabelle "Pages", so könntest du in dem Feld "slug" einfach den Kompletten Pfad speichern. Im PHP machst du dann eine Querry und liest alle Datensätze aus der Tabelle aus Du kannst dann über diese iterieren und Route::add dann dynamisch aufbauen. Pseudocode:

    foreach($pages as $page) {
    Route::add($page['slug'])', function($v) {
    // load your theme and push the page data to it
    }, ['get']);
    }
  3. Nutze Teildynamische routen. Angenommen du hast einen Blogbereich so liegen die Beiträge evtl. immer unter /blog. In der entsprechenden Tabelle speicherst du nun nur den Teil-Slug des Blogposts. Also zum Beispiel "mein-toller-artikel-uerber-php". Dann gehst du ähnlich vor wie bei Punkt 2 und registrierst alle blog-beiträge als route. Pseudocode:

    foreach($posts as $post) {
    Route::add('/blog/'.$post['slug'])', function($v) {
    // load your theme and push the post data to it
    }, ['get']);
    }

Mit wachsender Zahl an Seiten oder Posts werden die Methoden 2 und 3 halt langsam, weil immer alles aus den Tabellen geladen und als Route registriert wird. Darum kannst du dir auch überlegen das System umzukehren und nur eine Route für den Blog anlegen. Pseudocode:

Route::add('/blog/([a-z0-9-_]*)')', function($slug) {
    // load only this post
    // SELECT * FROM post WHERE slug = $slug (Note: Use mysqli to escape the $slug string for security reason!)
    // Trigger your own 404 logic if the slug was not found
  }, ['get']);

Wie du siehst gibt es viele Wege. Es kommt eben darauf an, was du genau machen willst. Letztendlich werden sich diese Methoden in einem Projekt evtl. auch mischen.

Nex4T commented 4 years ago

Grüß dich, hab das hier relativ spät gesehen, hab jetzt folgendes gemacht

`if ($result2 = $con->query($query2)) { while ($row2 = $result2->fetch_assoc()) {

    $townname = utf8_encode($row2["name"]);
    $search  = array('ö', 'ä', 'ü', 'Ö', 'Ä', 'Ü', ' ');
    $replace = array('oe', 'ae', 'ue', 'oe', 'ae', 'ue', '-');
    $newcityname = str_replace($search, $replace, $townname);

    Route::add('/'.strtolower($newcityname), function() {
        $_SESSION['townname'] = $newcityname;
        $townname = $_SESSION['townname'];
        frontendHead($townname);
        frontendNavi($townname);
        frontendContentExplorer('startseite');
        frontendFooter();
        frontendEnd();
    });
}
$result2->free();

} ` nur wie kann Ich jetzt fixen routen auch was übermitteln? Iach brauch die daten aus der db jeweils in der Session, wenn ich z.b auf den link /muenster klicke brauch ich münster in der session

steampixel commented 4 years ago

Hey. Ich habe absolut keine Idee, warum du beim Routing die Session brauchen solltest.

btinet commented 4 years ago

Angenommen der Link citi/muenster wird aufgerufen, wäre es dann nicht sinnvoll, wenn man den Namen der Stadt aus der Datenbank mithilfe des Links abruft?

Zum Beispiel

Id 1 slug muenster name Münster

Dann müsste man auch nichts im String ersetzen. Ich würde dann auch eher die id in der Session speichern, um später weitere Daten aus der entsprechenden Zeile zu holen.

Nex4T commented 4 years ago

ja gut das könnte ich auch machen mit der id aber die wird nicht übernommen, das ding ist hinter jeder stadt stecken noch viele andere daten, wie ich jetzt was speicher um an die daten zu kommen ist eigentlich egal, ich brauche sie halt einfach, nur das ding ist ich kann nach wie vor nichts übergeben

Nex4T commented 4 years ago

Also vorher hab ich es so gemacht

Route::add('/(.*)', function($v) {

hat auch Funktioniert, allerdings wenn ich jetzt etwas eingebe was nicht in der Datenbank steht wie z.b /google, wird die Route trotzdem ausgeführt halt ohne ausgaben dahinter .

deswegen dachte ich mir ich mache es wie im beispiel lasse es über eine schleife ausgeben und jeweils bei der Route id oder name ( was für mich keine relevanz hat ) der stadt in eine session speichern das ich anschließend damit weiter arbeiten kann, auf allen anderen subpages etc.

mein Problem ist nun da ich ja jetzt feste Routen setze krieg ich den wert nicht mehr in die Session

steampixel commented 4 years ago

Was willst du denn genau übergeben? Hast du ein Formular oder so? Oder Mehrere Formulare auf mehreren aufeinander folgenden Seiten? Ich verstehe das Problem noch nicht ganz. Ich würde dir bei sowas aber empfehlen die Daten zunächst im Frontend zu sammeln (JavaScript und LocalStorage) und dann alles am Ende an eine einzige Api zu posten. Das macht alles sauberer.

Nex4T commented 4 years ago

In erster Linie möchte ich nur den Stadtnamen im Link sowie im Content haben, alles weitere kann ich ja dann dort verarbeiten, ich lasse ja jetzt in der Schleife die Routen ausgeben nur bekomme ich danach den Stadtnamen nicht mehr im Content rein. Die variable $stadt würde ich gerne auf der unterseite ausgeben lassen aber funktioniert nicht, deswegen wollte ich das ja in die Session packen.

`if ($result2 = $con->query($query2)) { while ($row2 = $result2->fetch_assoc()) {

    $townname = utf8_encode($row2["name"]);
    $search  = array('ö', 'ä', 'ü', 'Ö', 'Ä', 'Ü', ' ');
    $replace = array('oe', 'ae', 'ue', 'oe', 'ae', 'ue', '-');
    $newcityname = str_replace($search, $replace, $townname);

    Route::add('/'.strtolower($newcityname), function() {
        $stadt = $newcityname;
        frontendHead($newcityname);
        frontendNavi($newcityname);
        frontendContentExplorer('startseite');
        frontendFooter();
        frontendEnd();
    });
}
$result2->free();

} `

steampixel commented 4 years ago

Hi,

ich würde das nicht in die Session packen. Denn die Unterseiten können theoretisch ja auch aufgerufen werden, wenn du vorher nicht schon auf der Übersichtsseite warst. Dann musst du dir ja wieder was bauen, dass wenn ein Wert in der Session fehlt, du wieder auf die Übersicht leitest oder sowas, damit das alles richtig initialisiert wird.

Warum registrierst du nicht für jede Stadt mehrere Routen? Das Schema (Name der Unterseiten) ist doch sicher immer gleich oder? Also, dass du in jedem Schleifenduchlauf die Hauptseite regisitrierst und dann gleich noch die Unterseiten:

while(...) {
Route::add('/'.strtolower($newcityname).'/edit', function() {
...
    });
Route::add('/'.strtolower($newcityname).'/details', function() {
...
    });
Route::add('/'.strtolower($newcityname).'/do-something', function() {
...
    });
}

Alternativ (Was ich empfehlen würde, weil es bestimmt viele Städte gibt) klannst du auch "Actions" nutzen. Also einen zweiten Parameter, der den Typ der Unterseite steuert:

Route::add('/([a-z0-9-_]*)/([a-z0-9-_]*)')', function($city, $action) {

// Select this city from db

// Switch the action
switch ($action) {
    case 'edit':
        // edit this city
        break;
    case 'details':
        // Show city details
        break;
    case 'do-something':
        // Mach irgendwas
        break;
}

  }, ['get']);
schlossmacher123 commented 4 years ago

i have the same problem, i cant use vars out of the route in the route

$fortest = '1'; Route::add('/test', function ($v) { echo $fortest; echo 'hallo'; }, ['get', 'post']);

dont work

steampixel commented 4 years ago

@schlossmacher123 Please refer to this solution: https://github.com/steampixel/simplePHPRouter/issues/31