title: PHP Slim 4 HttpNotFoundException -- Routes not found when moving application to live server
body: <p>I have a WordPress website that I have extended with the <code>Slim Framework</code> to provide some custom API. Everything works fine in local, but when I move the application on a live server (SiteGround), if I try to call any of the custom endpoints I get a <code>404 error Slim\Exception\HttpNotFoundExceptio</code>.</p>
  <p>This is my folder structure</p>
  <p>In Local the <code>root</code> folder is <code>C:\xampp\htdocs\example\</code></p>
  <p>In remote the <code>root</code> folder is <code>/home/customer/www/example.com/public_html/</code></p>
  <pre><code>api\
    vendor\
    public\
      .htaccess
      index.php
    routes\
      v1\
        autocomplete.php
    .htaccess
    composer.json
    composer.lock
  wp-admin
  wp-content
  wp-includes
  ... all others WordPress files
  </code></pre>
  <p>In local I was able to call the endpoint <code>http://localhost/example/api/v1/autocomplete</code>, while on remote if I call <code>https://www.example.com/api/v1/autocomplete</code> I get a <code>404 not found error</code></p>
  <pre><code>code: 404
  file: &quot;/home/customer/www/example.com/public_html/api/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php&quot;
  line: 91
  message: &quot;Not found.&quot;
  type: &quot;Slim\Exception\HttpNotFoundException&quot;
  </code></pre>
  <p>As per <a href="https://www.slimframework.com/docs/v4/start/web-servers.html#apache-configuration" rel="nofollow noreferrer">Slim documentation</a> the Apache <code>mod_rewrite</code> is enabled by the default WordPress <code>.htaccess</code> and <code>AllowOverride All</code> is <a href="https://www.siteground.com/kb/is_it_possible_to_set_apaches_allowoverride_directive_to_all/" rel="nofollow noreferrer">setted by default on all SiteGround server</a>.</p>
  <p>Here is the content of the important Slim files</p>
  <p>root\api\.htaccess</p>
  <pre><code>RewriteEngine on
  RewriteRule ^$ public/ [L]
  RewriteRule (.*) public/$1 [L]
  </code></pre>
  <p>root\api\public\.htaccess</p>
  <pre><code># Redirect to front controller
  RewriteEngine On
  # RewriteBase /
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^ index.php [QSA,L] 
  </code></pre>
  <p>root\api\public\index.php</p>
  <pre><code>&lt;?php
  use Selective\BasePath\BasePathMiddleware;
  use Slim\Factory\AppFactory;
  
  require_once __DIR__ . &quot;/../vendor/autoload.php&quot;;
  
  $app = AppFactory::create();
  
  // Add Slim routing middleware
  $app-&gt;addRoutingMiddleware();
  
  // Set the base path to run the app in a subdirectory.
  // This path is used in urlFor().
  $app-&gt;add(new BasePathMiddleware($app));
  
  $app-&gt;addErrorMiddleware(true, true, true);
   
  // PUT ALL ROUTES HERE
  require_once &quot;../routes/v1/autocomplete.php&quot;;
  
  // Run app
  $app-&gt;run();
  </code></pre>
  <p>root\api\routes\v1\autocomplete.php</p>
  <pre><code>&lt;?php
  use Psr\Http\Message\ResponseInterface as Response;
  use Psr\Http\Message\ServerRequestInterface as Request;
  
  $app-&gt;get(&quot;/v1/autocomplete&quot;, function (Request $request, Response $response) {
    $params = $request-&gt;getQueryParams();
    $payload = array(
      &quot;status&quot; =&gt; &quot;error&quot;,
      &quot;message&quot; =&gt; &quot;missing param 'user_input'&quot;,
    );
    if (isset($params[&quot;user_input&quot;])) {
      $payload = getSuggestions($params);
    }
    $response-&gt;getBody()-&gt;write(json_encode($payload));
    return $response
      -&gt;withHeader(&quot;Content-Type&quot;, &quot;application/json&quot;);
  });
  </code></pre>
  <p>Thanks in advance</p>