11
votes

After a little bit of research and have been unable to locate a solution to my problem. I am utilizing an API that is namespaces that I downloaded via composer. The API has it dependences that I allow composer to manage and autoload for me. Separate from this I have about 10 classes that I have autoloaded with utilizing php's spl_autoload_register. Recently, I started mixing the classes to finish up part a project and the whole thing has gone to crap. My custom classes cannot use the composer classes and visa versa. Is there a method I can use to autoload classes that are in two separate folders and that are loaded with two separate outloader.

Here is the code that I currently use. The vender/autoload.php is no different then your typical composer autoloader. Thanks for any assistance.

require 'vendor/autoload.php';
require 'functions/general.php';
require 'include/mailgun.php';

function my_autoloader($class) {
    require 'classes/' . $class . '.php';
}
spl_autoload_register('my_autoloader');
3

3 Answers

6
votes

Well, actually composer utilizes spl_autoload_register, so answer is 'yes', they can. The autoloading mechanism is supported by autoloader stack - basically, if class didn't appear in runtime after one autoloader has been run, next one is used, until stack runs out of autoloaders and PHP reports an error about a class it can't find. Every spl_autoload_register call basically adds new autoloader, so there may be plenty of autoloaders in memory. The main point of this story is autoloader that can't load class does nothing, the autoloading block of code simply ends with no action taken so next autoloader may take responsibility of class loading. The only thing you need to implement is check in your autoloader that it can handle current class loading (checking that file exists before requiring it is enough, though you should think about possible directory nesting in case of namespaces), and everything should work smooth in future:

function my_autoloader($class) {
    $path = sprintf('classes/%s.php', $class);
    if (file_exists($path)) {
        require 'classes/' . $class . '.php';
    }
}
6
votes

After further research due to ideas that the both @Etki and @Sarah Wilson gave me I came up with the following solution. Thank You both for your input.

require 'vendor/autoload.php';
require 'functions/general.php';
require 'include/mailgun.php';


function autoLoader ($class) {
  if (file_exists(__DIR__.'/classes/'.$class.'.php')) {
    require __DIR__.'/classes/'.$class.'.php';
  }
}
spl_autoload_register('autoLoader');

Hint: I added the __DIR__ to the beginning of the file paths inside the autoLoader function.

4
votes

If this is for a small project where you are including files from two or three folders you can use a simple if statement.

function my_autoloader($class) {
    if(file_exists('functions/'.$class.'.php')){
      require 'functions/'$class.'.php';
    } else if(file_exists('vendor/'.$class.'.php')){
      require 'vendor/'.$class.'.php';
    } //add more as needed
}
spl_autoload_register('my_autoloader');

For larger applications, I recommend naming your classes files and your classes for what they are or do, and have them in a specific folder by their names Example: controllers/userController.php for userController class functions/generalFunctions.php generalFunctions class then you can check the names and if it has controller then you include it from the controllers folders. Create an array within the my_autoloader function or in a separate file like.

loadMap.php

return [
   'controller' => 'path/to/controllers/',
   'function' => 'path/to/functions/',
   'helper' => 'path/to/helpers',
   'etc' => 'path/to/etc/'
]

filewithautoloadfunction.php

function my_autoloader($class){
  $loadMap = require 'path/to/loadMap.php';

  foreach($loadMap as $key => $path){
   if(stripos($key, $class){
    require_once $path.$class.'.php';
   }
  }
}

spl_autoload_register('my_autoloader');