'autoloading when there are multiple entry points for an app
In a PHP app, built for the purpose of handling API requests, the basic flow is like this:
.htaccess file excerpt:
RewriteRule ^api/account/?$ Modules/Account/AccountController.php [nc,L]
Modules/Account/AccountController.php:
require_once('../../Config/Config.php');
$allData = (new ControllerHelper())::getAllData();
$webServiceInstance = new AccountWebService($allData);
echo $webServiceInstance->submitRequest();
Config/Config.php excerpt for autoloading:
// ROOT is used in multiple places in the app, thus the constant
define('ROOT', $_SERVER['DOCUMENT_ROOT'] . '/MyApp/');
# autoloader
// recurses through project directory and builds associative array with file name as key and fully qualified file name as value (restrictions: file names end with .php, exclude index.php)
// autoloader function loads class files by matching class name to file name key in array to get path value
// note: RecursiveIteratorIterator returns an associative array with fully qualified file name as key and SplFileInfo Object as value
$projectDirectory = ROOT;
$ignore = ['.git','_Logs'];
$directory = new RecursiveDirectoryIterator($projectDirectory, RecursiveDirectoryIterator::SKIP_DOTS);
$directory = new RecursiveCallbackFilterIterator($directory, fn($current) => !in_array($current->getFilename(), $ignore));
$objects = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::LEAVES_ONLY);
foreach (iterator_to_array($objects) as $fullFileName => $splFileInfoObject) {
$fileNameWithExtension = $splFileInfoObject->getfileName();
if (substr($fileNameWithExtension, -4) == '.php' && $fileNameWithExtension != 'index.php') {
$fileName = pathinfo($fileNameWithExtension, PATHINFO_FILENAME);
$files[$fileName] = $splFileInfoObject->getPathname();
}
}
// exit('<pre>' . print_r($files, 1) . '</pre>');
define('FILES', $files);
spl_autoload_register(fn($className) => require_once(FILES[$className]));
While this works, the performance is horrible because every time an API endpoint is hit the project directory is recursed. It could be improved by recursing the project directory once - say if the entry point were index.php and the recursion logic for the autoloader could be moved there. However, the various endpoints enter the app using their respective controller.php files.
I've investigated preloading a script using php.ini but that isn't available on Windows so it's not an option.
Also worth mentioning - the Modules directory is where the business related files live. That directory has a lot of activity with new subfolders being added frequently as new parts of the app are built. Thus the desire for an autoloader that can just recognize new subfolders and files.
Also, this app is not namespaced.
Is there a way leverage the directory recursion somehow just once when multiple entry points are being used for the endpoints and if so, how?
EDIT
Here is a larger excerpt from .htaccess to help explain what I mean by several API endpoints -
RewriteRule ^api/account/?$ Modules/Account/AccountController.php [nc,L]
RewriteRule ^api/account/([0-9]+)/?$ Modules/Account/AccountController.php?accountId=$1 [nc,qsa,L]
RewriteRule ^api/account/email/(\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b)/?$ Modules/Account/AccountController.php?email=$1 [nc,qsa,L]
RewriteRule ^api/item/?$ Modules/Item/ItemController.php [nc,L]
RewriteRule ^api/item/([0-9]+)/?$ Modules/Item/ItemController.php?itemId=$1 [nc,qsa,L]
RewriteRule ^api/warehouse/?$ Modules/Warehouse/WarehouseController.php [nc,L]
RewriteRule ^api/warehouse/([0-9]+)/?$ Modules/Warehouse/WarehouseController.php?warehouseId=$1 [nc,qsa,L]
RewriteRule ^api/warehouse/item/([0-9]+)/?$ Modules/Warehouse/WarehouseController.php?itemId=$1 [nc,qsa,L]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
