0

I have developed a PHP API to be consumed by a JavaScript frontend. I will make requests through fetch/ajax. When I start my server, I can't have an index.php file to call my route file because my application will be accessed through an index.html. How can I ensure that my frontend application can access, for example, the address www.example.com and display my HTML, and when my JavaScript makes an AJAX request to www.example.com/api/uri, it accesses my API?

My route file is inside app/routes/Router.php that is working fine

Here is the file:

<?php

namespace app\routes;

use app\helpers\Request;
use app\helpers\RouteParamParser;
use app\helpers\Uri;

class Router
{

    const CONTROLLER_NAMESPACE = 'app\\controllers';

    public static function load(string $controller, string $method, $request = null, $routeParams = [])
    {
        try {
            // Check if controller exists
            $controllerNamespace = self::CONTROLLER_NAMESPACE . '\\' . $controller;
            if (!class_exists($controllerNamespace)) {
                throw new \Exception("O Controller {$controller} não existe");
            }

            $controllerInstance = new $controllerNamespace;

            if (!method_exists($controllerInstance, $method)) {
                throw new \Exception("O método {$method} não existe no Controller {$controller}");
            }

            $controllerInstance->$method($routeParams, $request);
        } catch (\Throwable $th) {
            echo $th->getMessage();
        }
    }

    public static function routes(): array
    {
        return [
            'get' => [
                '/api/locations' => ['controller' => 'LocationController', 'method' => 'index'],
                '/api/locations/{id}' => ['controller' => 'LocationController', 'method' => 'show'],
                '/api/departments' => ['controller' => 'DepartmentController', 'method' => 'index'],
                '/api/departments/{id}' => ['controller' => 'DepartmentController', 'method' => 'show'],
                '/api/personels' => ['controller' => 'PersonelController', 'method' => 'index'],
                '/api/personels/{id}' => ['controller' => 'PersonelController', 'method' => 'show'],
            ],
            'post' => [
                '/api/locations' => ['controller' => 'LocationController', 'method' => 'store'],
                '/api/departments' => ['controller' => 'DepartmentController', 'method' => 'store'],
                '/api/personels' => ['controller' => 'PersonelController', 'method' => 'store'],
            ],
            'put' => [
                '/api/locations/{id}' => ['controller' => 'LocationController', 'method' => 'update'],
                '/api/departments/{id}' => ['controller' => 'DepartmentController', 'method' => 'update'],
                '/api/personels/{id}' => ['controller' => 'PersonelController', 'method' => 'update'],
            ],
            'delete' => [
                '/api/locations/{id}' => ['controller' => 'LocationController', 'method' => 'destroy'],
                '/api/departments/{id}' => ['controller' => 'DepartmentController', 'method' => 'destroy'],
                '/api/personels/{id}' => ['controller' => 'PersonelController', 'method' => 'destroy'],
            ],
        ];
    }

    public static function execute()
    {
        try {
            $routes = self::routes();
            $request = Request::get();
            $uri = Uri::get('path');
    
            if (!isset($routes[$request])) {
                throw new \Exception('A rota não existe');
            }
    
            $routeParams = [];
            $router = null;
    
            // check if exact route exists
            if (isset($routes[$request][$uri])) {
                $router = $routes[$request][$uri];
            } else {
                // Search for route with params
                foreach ($routes[$request] as $route => $routeConfig) {
                    $parsedRoute = RouteParamParser::getRouteParams($route);
                    if ($parsedRoute !== null) {
                        $pattern = str_replace('/', '\/', $route);
                        $pattern = preg_replace('/{.*?}/', '(.*?)', $pattern);
                        if (preg_match('/^' . $pattern . '$/', $uri, $matches)) {
                            $routeParams = $parsedRoute;
                            $router = $routeConfig;
                            break;
                        }
                    }
                }
            }
    
            if (!$router) {
                throw new \Exception("Route not found");
            }
    
            $controller = $router['controller'];
            $method = $router['method'];
    
            self::load($controller, $method, $request, $routeParams);
        } catch (\Throwable $th) {
            echo $th->getMessage();
        }
    }
    
    
}

I'm not sure if I made myself clear, but I think I managed to convey what I need.

my repo to the code is https://github.com/vsrromero/companyDirectoryV2/

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • You don't need `index.php` if you're never using it. All you need is the PHP script for the API. – Barmar Jun 30 '23 at 19:23
  • The front-end should call the URL of the API. ```app/controllers/DepartmentController.php``` – Barmar Jun 30 '23 at 19:24
  • If you want to change the file that is accessed for the "home page", https://stackoverflow.com/questions/19322345/how-do-i-change-the-default-index-page-in-apache – imvain2 Jun 30 '23 at 19:55
  • 1
    A URL has nothing to do with any file on the server... – Honk der Hase Jun 30 '23 at 20:50
  • "I can't have an index.php file to call my route file because my application will be accessed through an index.html" — I honestly don't know what you mean here. `index.html` is just the default value for the default document that Apache serves when you don't specify any (see [DirectoryIndex](https://httpd.apache.org/docs/2.4/en/mod/mod_dir.html#directoryindex)), but it doesn't prevent other URLs from existing. Perhaps you want [FallbackResource](https://httpd.apache.org/docs/2.4/en/mod/mod_dir.html#fallbackresource) inside `/var/www/html/api/` (or whatever path) to build friendly URLs? – Álvaro González Jul 01 '23 at 07:51
  • @Barmar but here is my question, if I call straight my app/controllers/... it means I do not need a route file, right? So, how someone that is not on same domain will access my api as well? – Victor Romero Jul 02 '23 at 15:49
  • You use a route file to avoid having to duplicate the same common code in every controller, it's by no means a security mechanism. You don't really access API end-points from domains, that isn't HTTP works. You can e.g. run `curl` in a terminal. Using `index` for route files and default documents is just a convention, you can call it `router.php` or `foobar.php` if you want. – Álvaro González Jul 03 '23 at 06:12
  • Thank you @ÁlvaroGonzález, I'll use this approach – Victor Romero Jul 04 '23 at 14:56

0 Answers0