I am writing a website in PHP, using an Apache server. I need to redirect from the address of www, human-readable URLs, redirect to canonical URLs, multilingual, ban some user agents, ban users by IP and many more using mod_rewrite, with all this configured through the admin area.

How can I do it?

    2 answers 2

    You are going the wrong way. If you do everything through mod_rewrite, then you will encounter a bunch of problems:

    • You will get bogged down in tons of unreadable and unsupported code. This language is not intended for complex logic, although it is conditionally Turing-complete.

    • You tightly nail your site to the Apache server. If you want to use nginx, then you will have serious problems.

    • Debugging the rules is almost impossible. If you encounter a bug that is not corrected by a close look at the code, then it will be difficult to find an error.

    • If you have rules editable through the admin panel (human-readable URLs, banned IP ranges, etc.), then programmatically editing .htaccess will be problematic.

    In modern frameworks and CMS, routing through the front controller is commonly used. Here is all you need:

     RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?_route=$1 [L,QSA] 

    Now in index.php you will have a path to $_GET['_route'] , all other parameters in the GET request will also be saved. You can write whatever logic you want in a language that you know and understand well, using any means like access to the configuration to get the routing settings and access to the database to get banned IP ranges.

    If you are not confused by accessing the path via $_SERVER['REQUEST_URI'] instead of $_GET['_route'] , then you can simplify .htaccess even more, as indicated in the notes to another answer:

     RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . index.php [L,QSA] 

    PS Canonical URLs are usually sufficient to specify in the page meta-information. Redirects due to the lack of / at the end only waste resources.

    • Can I use an example on js or php? - spectre_it
    • 2
      @ stack-it If you do routing on your knee, and not using libraries or frameworks, then I would do it on regulars. Anything in the spirit of [ $controller, $action, $argument ] = preg_match('/^ / (\w+) / (\w+) (?: / (\w+) ) $/x', $_SERVER['REQUEST_URI']); switch ($controller) { case 'home': switch ($action) { case 'index': /*...*/ [ $controller, $action, $argument ] = preg_match('/^ / (\w+) / (\w+) (?: / (\w+) ) $/x', $_SERVER['REQUEST_URI']); switch ($controller) { case 'home': switch ($action) { case 'index': /*...*/ . Well, or immediately if (in_array($controller, [ 'home', /*...*/ ]) && in_array($action, [ 'index', /*...*/ ])) include("controllers/$controller.php"); (with this approach, validation of strings on the white list is required). - Athari

    For reasons of the question: Why eats a slash in the bracket group of a regular expression?

    If you use redirection like this:

     RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?_route=$1 [L,QSA] 

    That at request of a type

     http://localhost//activation-account/$2y$10$Xl40W/SKTOXYcxfCxGszr.9tbd//lNJSVJTpBh4umjWf/9GNMSlJy/loginfiko 

    in the $_GET['_route'] variable we get the wrong result:

      activation-account/$2y$10$Xl40W/SKTOXYcxfCxGszr.9tbd/lNJSVJTpBh4umjWf/9GNMSlJy/loginfiko 

    Double slash replaced by single!

    I think that it is more appropriate to use redirection like this:

     RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} ^(.*)$ RewriteRule ^ index.php?_route=%1 [L,QSA] 

    Then in the variable $_GET['_route'] we get the result:

      /activation-account/$2y$10$Xl40W/SKTOXYcxfCxGszr.9tbd//lNJSVJTpBh4umjWf/9GNMSlJy/loginfiko 

    Double slashes on the spot + second slash after the host hit the variable.

    PS Nobody has canceled the $_SERVER['REQUEST_URI'] variable, the contents of which can be parsed as you like.

    • 2
      Hmm, I like the RewriteRule . index.php [L,QSA] RewriteRule . index.php [L,QSA] - we take even more from mod_rewrite. :)) - Athari
    • @Squidward, for this business I wrote PS - Visman