How can I reconcile SplClassLoader's namespace requirement with my custom directory layout?

StackOverflow https://stackoverflow.com/questions/13919974

  •  10-12-2021
  •  | 
  •  

Domanda

I recently starting writing a custom MVC framework in PHP. It's basically a learning exercise.

My classes are located in the following directories:

  • system/libraries/
  • system/controllers/
  • system/models
  • application/libraries/
  • application/controlers/
  • application/models

I'm not using namespaces because I can't figure out how to instantiate controllers using namespaces and Apache 2 handler style URLs (controller/action/id). I created a Bootstrap class to autoload my other classes:

class Bootstrap
{
  public function autoloadClasses($class)<br/>
  {
    $class .= '.php';

    $classDirectories = array(
        SYSTEM_LIBS_DIR,
        SYSTEM_CONTROLLERS_DIR,
        SYSTEM_MODELS_DIR,
        APPLICATION_LIBS_DIR,
        APPLICATION_CONTROLLERS_DIR,
        APPLICATION_MODELS_DIR
    );

    foreach ($classDirectories as $classDirectory) {
        $directoryIterator = new DirectoryIterator($classDirectory);
        foreach($directoryIterator as $file) {
            if ($file == $class) {
                include $classDirectory . $class;
                break 2;
            }
        }
    }

  }


  public function register()
  {
    spl_autoload_register(array($this, 'autoloadClasses'), true);
  }


  public function init()
  {
    $this->register();
    $loader = new Loader($_GET);
    $controller = $loader->createController();
    $controller->executeAction();
  }
}

It works fine. However, I know I should really be using the implementation recommended by PSR-0:

https://gist.github.com/221634

However, I can't figure out how to get it to work without namespaces. It looks like the namespace is an optional pararmeter. However, if I do the following, nothing happens -- not even an error in the Apache logs:

$libLoader = new SplClassLoader('', 'system/libraries');
È stato utile?

Soluzione

The goal of PSR-0 was to try and specify how external third-party library classes should be named, and where the files containing those classes should live on disk. This goal was accomplished, and from a high level, it's not too bad of a thing. Interopability and not stepping all over other libraries is a good thing.

Your directory layout and class naming scheme doesn't mesh with PSR-0, which means SplClassLoader is going to be nigh-useless for you.

You have two options:

  1. Rename all of your classes, shuffle them into a namespace hierarchy, and refactor the rest of the code that needs to worry about it, or
  2. Don't use SplClassLoader and write your own autoloader.

If you're building a library intended for external distribution, it'll be a good idea to make yourself PSR-0 compliant, as it's pretty darn simple, logical and painless.

If you're building your own app for your own use and don't intend it as a library, then you are under no requirement to do all of that work, and you shouldn't, because it'd be silly. This looks like it's the case, so I can end with a big fat: don't bother.

Altri suggerimenti

I got it to work. YAY!

Here is the code from my front controller (index.php) I'm going to refactor it since it would be cleaner to simply make one call to some type of bootstrap class:

<?php
use NeilMVC\system\libraries\Loader;
require_once('conf/conf.php');
require_once('SplClassLoader.php');

$loadSystemLibraries = new SplClassLoader('NeilMVC\system\libraries'); 
$loadSystemControllers = new SplClassLoader('NeilMVC\system\controllers');
$loadSystemModels = new SplClassLoader('NeilMVC\system\models');

$loadApplicationLibraries = new SplClassLoader('NeilMVC\application\libraries');
$loadApplicationControllers = new SplClassLoader('NeilMVC\application\controllers');
$loadApplicationModels = new SplClassLoader('NeilMVC\application\models');

$loadSystemLibraries->register();
$loadSystemControllers->register();
$loadSystemModels->register();

$loadApplicationLibraries->register();
$loadApplicationControllers->register();
$loadApplicationModels->register();

$loader = new Loader($_GET);
$controller = $loader->createController();
$controller->executeAction();

I had to refactor some of the classes in order to resolve fully qualified classes to unqualified names used in the MVC-style URLs. It wasn't that hard to do, I just had to tinker with it to understand it. If anyone want to know more, you can email me through my website http://neilgirardi.com

Cheers and happy holidays!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top