PHP Built-in and htaccess - Route System / User Friendly URL

Asked

Viewed 1,220 times

3

I have a file. htaccess for route diversion on the server (production) and a router.php file for route diversion using PHP 7’s Built-in server.

php -S 0.0.0.0:8000 router.php

However, I would like to use the php router. also in production, with the same effect.

My server is managed with WHM and domains with Cpanel (also with PHP 7, with the same location settings).

Note that it is not just about putting the content in the index php., or transfer responsibility via . htaccess, since the route file has specific commands, such as the famous...

return false;

...to indicate that the php router. should be ignored and go straight to the URI folder.

And that doesn’t work on a common access.

Practical example (purely educational):

Project Folders/Files

1 - /api/execute.php
2 - /admin/
3 - /index.php

Routes (URI of Origin):

1 - /api/{servico}/{detalhe}
2 - /admin/
3 - /{caminho}/{qualquer}

What . htaccess looks like (production):

RewriteEngine On
RewriteRule ^api/?.*$ api/execute.php [NC,L]
RewriteRule ^admin/?(.*)$ admin/$1 [NC,L]
RewriteRule ^/?.*$ index.php

How does the router.php (local/Built-in):

<?php
if (php_sapi_name() === 'cli-server' && is_file(__DIR__ . parse_url($_SERVER[ 'REQUEST_URI' ], PHP_URL_PATH))) {
    return false;
}

// Inicializa serviço de controle de URI
$uri = new \Config\Uri();

// API
if (preg_match('/^api\/?.*$/', $uri->getUri())) {
    require_once 'api/execute.php';
    exit;
}

// ADMIN
if (preg_match('/^admin\/.*$/', $uri->getUri())) {
    return false;
}

// Site
require_once "index.php";

This is just an example, but note the use of return false;. All other lines of php router. work both locally and in production.

But the return false; which aims to bypass the router and follow the path of Uri naturally, does not work online, obviously.

How to proceed?

Obs: This is an old system that still needs support. It is not worth changing the whole route system of it, since a new system is being created. So I just wanted to use the same php router. tb in production not to have to use the . htaccess custom for each domain using the system.

  • 2

    What exactly is the problem? There is a lot of sparse information in the question, but perhaps it is better to focus on the difficulty faced, describe what has been tried and what the problem with trying. In theory, if you make the.php router meet all requests, it should work in both situations, no?

  • @Bacco ready, I put an example to explain better

  • You could explain yourself better?

  • What part, @Tmc? Please see the examples. I need to develop a.php router that works for both the built-in php and the online server, for the past example. Note that the only part that doesn’t work online are the ones that involve using "Return false"

  • 1

    A few months ago I published an answer that solved this: http://answall.com/a/117757/4793 At this link it seems that AP did not understand anything. I know it may seem complex, but if you want I can explain the use that is actually quite simple and has support even for executions by command line interface (CLI).

  • @Danielomine Thanks for the link. In fact, it helps a lot, but does not seem to solve. The direct links to file worked, but the direct links to folders did not. I may not have configured it correctly. Using the example I gave you, would you please show me how to configure htaccess (and the router if necessary) so that it works properly? (Especially when accessing another folder, which will contain its own rules, such as the "/admin/" of the example...). Already create an answer here, please, since if you solve, the reward is yours ;) In addition to helping others too

Show 1 more comment

1 answer

2

Let’s see if I can help, and if I understand the question.

I leave here an excerpt of the code I use in a framework I developed over the years, and which I use in several PHP projects.

First of all, what we want is a single point in PHP that is responsible for all the routing logic, and for that we have to have something like this in the file. htaccess:

RewriteRule ^/?.*$ /pageHandler.php?CUSTOM_HTACCESS_VAR=$1 [QSA,NC,L]

This will redirect all requests to pageHandler, and all URL data will be accessible at $_GET['CUSTOM_HTACCESS_VAR'] (alternatively This can also be done and accessed through internal PHP variables such as $_SERVER['REQUEST_URI'])

In pageHandler, we create an instance of my Parsing class, and we call the processPage method.

Parser class content is here (only the relevant part):

<?php
class Parser {
    var $URL;
    var $file; // the current PHP file being used
    var $vars;
    var $path;
    var $timer;
    var $fullPathExists = true;

    function __construct() {
        $this->requestID = uniqid(md5(rand()), true);

        $varName = "CUSTOM_HTACCESS_VAR";
        $this->URL = array();
        if (isset($_GET[$varName])) {
            if (substr($_GET[$varName], 0, 1) == "/") $_GET[$varName] = substr($_GET[$varName], 1);
            $url = explode("/", $_GET[$varName]);
            $this->URL = $url;
        }

        unset($_GET[$varName]);
        $this->vars = array();
        $this->path = array();

        $dir = "{$_SERVER['DOCUMENT_ROOT']}/Pages/";
        $tamanhoURL = count($this->URL);
        for($i = 0; $i < $tamanhoURL; $i++) {
            $tempDir = "{$dir}{$this->URL[$i]}/";
            if (!is_dir($tempDir)) {
                break;
            }
            $dir = $tempDir;
            $this->path[] = $this->URL[$i];
        }

        # verifica se existe dentro da ultima pasta um ficheiro com o nome que nao é o index
        if (($i < $tamanhoURL) && file_exists("{$dir}{$this->URL[$i]}.php")) {
            $file = "{$dir}{$this->URL[$i]}.php";
            $script = $this->URL[$i];
            $this->path[] = $this->URL[$i];
            $i++;
        }
        else {
            $file = "{$dir}index.php";
            $script = "index";
        }

        $this->file = $file;

        for (;$i < $tamanhoURL - 1; $i++) {
            $this->vars[$this->URL[$i]] = $this->URL[++$i];
            $this->fullPathExists = false;
        }
        if ($i < $tamanhoURL) {
            $this->vars['SINGLE'] = $this->URL[$i];
            $this->fullPathExists = false;
        }

    }


    function processPage() {
        if (file_exists($this->file)) {
            require($this->file);
        }
        else {
            header("HTTP/1.0 404 Not Found");
            header("Status: 404 Not Found");
        }
    }
}
?>

I hope it helps. You may have to adapt the code to work on these sites that already have their own structure, which may differ from the one I use.

Note also that this class stores in a vars name variable all parts of the URL that do not correspond to a file, and that can be used in a MVC framework perspective.

For example, the URL /test/foo/do/action can be used to load the file /test/foo.php, and in the vars variable there is an element named 'do' with the action value'.

  • I appreciate the help, but that’s not it. Note that your class returns a 404 for when the file doesn’t exist. This means that q cannot call a folder in the URL (such as "/admin/", from the example). And the problem is right there. When - in the example - the url points to the admin folder, it should skip the routing and go there.

  • @Szag-Ot A small change in class or processPage is enough. As you can see, in the $this->path variable there is an array with the path that could be reconstructed and that can be used inside the Else of the processPage method, or access the local variable $dir that is used in the constructor.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.