13

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');
NorthCat
  • 9,643
  • 16
  • 47
  • 50
DevOverlord
  • 456
  • 3
  • 19

3 Answers3

7

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';
    }
}
Etki
  • 2,042
  • 2
  • 17
  • 40
6

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.

DevOverlord
  • 456
  • 3
  • 19
  • Hi, please can you explain better why you choose this solution, and what it does exactly? I think it can help other people better. Thank you – funder7 Nov 07 '21 at 20:05
  • Read the other answers as my answer was constructed from theirs, hence the Thank you's I gave them. This was 6 years ago my man, I don't remember my state of mind at the time and why I made that decision – DevOverlord Nov 10 '21 at 12:14
4

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');
  • When I plug in the small project version of your code I get the following: Welcome || <br/> <b>Fatal error</b>: Class 'Config' not found in <b>/var/www/html/395clan/include/head.php</b> on line <b>11</b><br/> – DevOverlord Mar 26 '15 at 11:28
  • PHP is not finding the file. You cannot use this auto-loader unless your class names are the same as the file. ex: Config.php for Config class. You also need to make sure that the path to each of the folders in the if/else statements are correct. – Sarah Wilson Mar 27 '15 at 04:53
  • Hey Sarah, THank for your help, I answered the question above. – DevOverlord Mar 27 '15 at 07:38
  • if(stripos($loadMap[$key], $class)){ work in foreach require – Mario Gonzales Flores Aug 13 '18 at 18:09