Search code examples
phpvercel

Simple PHP page routing + requires in Vercel


I'm trying to deploy a basic PHP website in vercel. The structure is like:

/index.php -- main page, generic menu in the middle

/index.php?page=contact_us --> `require`s "contact_us.html" in the center of index.php
/index.php?page=about_us --> `require`s "about_us.html" in the center of index.php

Index.php looks like this:

<html><head><!-- header html here --></head>
<body>
<?php
    if($_GET['page'] == 'about_us'){
        require "pages/about_us.html"
    }
    else{
        require "pages/menu.html";
    }
?>
<!-- footer components here -->
</body>
</html>

This structure lets me have a page where I don't have to repeat the header and footer. The vercel.json looks like this:

{
    "version": 2,
    "functions": {
        "api/index.php": {
            "runtime": "[email protected]"
        }
    },
    "routes": [
      { 
        "src": "/(css|js|img)/(.*)$",
        "dest": "/api/assets.php?type=$1&file=$2"
      },
      { 
        "src": "/page.php?page=(.*)$",
        "dest": "/api/index.php?page=$1" <--- this doesn't work
      },
      { 
        "src": "/(.*)",  
        "dest": "/api/index.php" 
      }
    ]
}

I've tried tons of different combinations, e.g.:

  • Could it be the php? with a question mark throwing off the regex? nope
  • Could I do src: /p/(.*) and then dest to api/index.php?page=$1 nope
  • Could I do just plain old src: /about_us and dest /api/index.php?page=about_us nope

None of these work. Any help?


Solution

  • You can try with this:

    { 
      "src": "/page\\.php(.*)",
      "dest": "/api/index\\.php$1"
    },
    
    // OR
    
    { 
      "src": "/page\\.php\\?page=(.*)",
      "dest": "/api/index\\.php\\?page=$1"
    },
    
    

    /page.php?page=contact_us will redirect to /api/index.php?page=contact_us.

    The real issue here is that the documentation lacks an important information: escaping special chars should be done not only in src but also in dest.

    The following characters (, ), {, }, :, *, +, ? are used for regex path matching, so when used in the source as non-special values they must be escaped by adding \ before them. Reference: https://nextjs.org/docs/pages/api-reference/next-config-js/redirects#regex-path-matching

    Anyway, routes is deprecated and you should use rewrites: https://vercel.com/docs/projects/project-configuration#upgrading-legacy-routes

    Here you can find hint on why you need to "double-escape" the dot using routes: https://vercel.com/docs/projects/project-configuration#legacy-pattern-matching