4

Im building a MVC PHP framework and am having some issues with autoloading my classes, which i think might be down to my file structure.

Firstly, here is my file structure:

enter image description here

Im testing developing in an Xampp localserver environment so this is why i have the private and public folders. Eventually on a live server the private folders will be in the server root and the public folders will be in the public_html directory.

Does my file structure look about right? in the private, frontend folder ill have all my different modules in directorys which inturn has a controller, model, view files which hold the neccessary files for each module.

I have created this autoloader so far:

    //Require config and router classes
require_once('router.class.php');
require_once('config.php');

spl_autoload_register(null, false);

spl_autoload_extensions('.class.php');

function autoloader_core($class){
    $filename = strtolower($class) . '.class.php';

    if(!file_exists($filename)){
        echo $filename . " not found";
    }
    include $filename;
}

function autoloader_app($class){
    $filename = strtolower($class) . '.class.php';
    $file = 'C:\xampp\htdocs\simplebids\simplebidsprivate\app/' . $filename;

    if(!file_exists($file)){
        echo $file . " not found";
    }
    include $file;
}

spl_autoload_register('autoloader_core');
spl_autoload_register('autoloader_app');

$router = new test;
$router->say_hello();

This works perfect for the classes within the lib->core directory, but when i try to instantiate a new test class i get all sorts of errors about not finding the test.class.php file in the lib->core file, which it obviously isn't but i thought the autoloader function would be looking in the path defined by myself in the "autoloader_app" function.

The funny thing is even though i get all these errors, the string i echo in the test function say_hello() does get echoed after the errors.

So in short the file isnt being found according to the errors, but it is because i can see the echo i made the classes function print.

Any ideas why?

Also my frontend module file structure, is this going to make autoloading very difficult as ill need a different autoloading function for every module and then every controller/model/view file in it? will i need a seperate autoloading function for every module? If not how would i go about it?

Thanks Tom

tereško
  • 58,060
  • 25
  • 98
  • 150
Tom Burman
  • 947
  • 3
  • 15
  • 37
  • where would you have your config files. Also, try adding a Plugin functionality. That would be required at a later stage if you are looking forward to publish the framework for public use – Guns Apr 11 '14 at 07:41
  • Not really answering your particular question, but you really should look at PSR-0 (and perhaps PSR-4) when it comes to autoloading. If you do, then you'll be able to mix and match other framewords that conform to PSR into yours (and the other way around as well). http://www.php-fig.org/psr/psr-0/ – Sarel Apr 11 '14 at 07:42
  • You should start using namespaces (PSR-0 will give you some direction for where to start) .. and stop using `.class` in your file names, because not all the things that you load will be classes. – tereško Apr 11 '14 at 08:15
  • This might help: http://stackoverflow.com/questions/5280347/autoload-classes-from-different-folders – kampfkuchen Aug 19 '14 at 18:59

1 Answers1

1

I would suggest the following approach. It is what I use for my own projects (including an MVC framework)

First, follow these rules:

  • One class/trait/interface per file.
  • Use the class/trait/interface name lowercased, as the file name. E.g. class Foo would be "foo.php"
  • Store namespaced class/trait/interface files in a directory tree matching the namespaces, with lowercase names. e.g. class \Foo\Bar\Baz would be "/foo/bar/baz.php"

Then, to activate the simplest autoloading you've ever seen:

Add the director(y/ies) containing all class files/directories to the php include path:

set_include_path(get_include_path() . PATH_SEPARATOR . ROOT_DIR . "/lib");

Load the builtin autoloader:

spl_autoload_register('spl_autoload', false);

So to give an example, this is the directory structure of my apps commonly:

Project Root/
|-apptopnamespace/
| |-controllers/
| | |-dashboard.php
| | |-users.php   
| |-models/
| | |-user.php   
| | |-item.php   
| |-etc/
| |-appname.php
| |-router.php
|-bootstrap.php

To simplify it, the framework has a method to setup stuff like autoloading, include paths etc.

So the following call is made in bootstrap.php. The argument could easily have more paths in the array (e.g. [__DIR__, __DIR__ . DIRECTORY_SEPARATOR . 'lib'] if you have a nested "lib" directory in the project folder):

Bamboo::configure([__DIR__]);

Internally the framework then (amongst other things) calls these two methods:

/**
 * Add one or more paths to the include path
 *
 * @param array $paths an array of paths to add to the include path
 */
protected static function addIncludePath(array $paths) {
    set_include_path(
        get_include_path() . PATH_SEPARATOR . implode(
            PATH_SEPARATOR,
            $paths
        )
    );
}

/**
 * Register the SPL Autoloader
 */
protected static function setupAutoload() {
    // Don't clobber any __autoload already defined
    if (function_exists('__autoload')) {
        spl_autoload_register('__autoload', false);
    }

    spl_autoload_register('spl_autoload', false);
}
Stephen
  • 18,597
  • 4
  • 32
  • 33