8

I'm developing a library for guitar chords. In some files on the library I have something like this:

require_once "lib/GuitarChord.php";
require_once "lib/Chord.php";
require_once "lib/Key.php";
require_once "lib/Tuning.php";

How can I make this library so it doesn't need to know where the other library files are?

This way a person could have the library files in any directory?

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
carlosdubusm
  • 1,063
  • 4
  • 11
  • 22

5 Answers5

6

Create autoloaders for all locations where these classes might be.

For Example:

//AUTOLOADER
function class_autoloader($class) {

   // presumes classes are in './classes'
   $folders = array(
     './', './../', './../../'  
   );
   $directories = array(
     'classes','lib',  ''
   );
   $dir = dirname(__FILE__);
   $theClass = '/' . $folderedClass . '.php';


   foreach($folders as $folder){
       foreach($directories as $directory){
           $theInclude = $dir.$folder.$directory.$theClass;

           if (file_exists($theInclude) && include_once($theInclude)) {
              return TRUE;
           } 
       }
   }

  trigger_error("The class '$class' or the file '$theClass' failed to spl_autoload ", E_USER_WARNING);

  return FALSE;
}

spl_autoload_register('class_autoloader');

Then if you want to load the Chord Class and you know it is in your lib folder, the autoloader will do the work for you when you do:

new Chord();

You can attach many different autoloader callbacks with spl_autoload_register

Naftali
  • 144,921
  • 39
  • 244
  • 303
  • Is there any way I can make the library know where the other files are located automatically? The other files will always be on the same directory as the library entry point. For ex. require "lib/glib.php"; glib is the entry point. All the other files are assumed to be on lib/. Is this possible? – carlosdubusm Sep 15 '11 at 22:38
  • @carlos -- this is `automatically` its called `autoload` – Naftali Sep 15 '11 at 22:39
1

You should check out namespaces and autoloaders.

Lets say you have all your classes within 'GuitarChords' namespace - so you can just create autoload function something similar to following (assuming file, where you register your autoloader is in parent directory of "lib"):

    spl_autoload_register(function($class){
       $namespace = explode('\\', $class, 2);
          if ($namespace[0] === 'GuitarChords' && isset($namespace[1])) {
             include(__DIR__.DIRECTORY_SEPARATOR.'lib'.DIRECTORY_SEPARATOR.$namespace[1].'.class.php');
          }
     });

I think it's better to register one autoload function for every library-set/namespace specifically. Iterating over directories and using include_once, file_exists etc. might produce some nasty IO overhead depending on complexity of your system.

Mikk
  • 2,209
  • 3
  • 32
  • 44
0

If your library uses all or most of the included classes then consider putting all of the classes related to your library in the same file. Other solutions are just going to involve adding more code in which case you should probably just stick with using your current method.

If you want the files split for development purposes then by all means continue to do so but you can still package it into one file for production use for people to easily include.

Naftali
  • 144,921
  • 39
  • 244
  • 303
Fake Code Monkey Rashid
  • 13,731
  • 6
  • 37
  • 41
  • 1st off - I did not downvote, second -- my issue with that is that you might load classes that you **do not need** if you make one **BIG** class file, might be better off with smaller files and an autoloader – Naftali Sep 15 '11 at 22:26
0

Somewhere you're going to have to include the folder name, if you don't want to include all your classes in one file. You can make it somewhere that the user only has to set once, though:

$lib_folder = "lib";

require_once $lib_folder . "/GuitarChord.php";
require_once $lib_folder . "/Chord.php";
require_once $lib_folder . "/Key.php";
require_once $lib_folder . "/Tuning.php";

As for handling different types of databases, you can make another setting like $db_type that the user either sets to "MYSQL", "FILE", "XML", etc. And where you make calls to the db, use a switch statement to see what database method they're using and change your call accordingly.

Edit: It's also worth looking into PHP's __autoload feature

rekamoyka
  • 1,122
  • 11
  • 15
0

You might want to try Zend AutoLoader.

JRL
  • 76,767
  • 18
  • 98
  • 146