Including/Requiring within an application

Howdy!

I find myself writing frameworks all the time, each with different features, different ways of going about things and different focuses.

Off Topic:

Strangely enough, I rarely do projects beyond the framework stage. I suppose its the theory and potential I enjoy rather than extending it to something useful. Anyone else in the same boat? :stuck_out_tongue:

One thing that I change between projects is the way one file imports another, inside an application. Usually the method I’d use is:

  1. The main application initial file loads all the function files
  2. It then loads the main system class files
  3. Autoloading is used to load models etc

However, one thing I’ve been using in my latest framework is include_once’ing all files required in every file. For example, if the action/view of a model needs to load model and a function file for creating a short summary from a larger text, it would start with:

<?php
require_once('Application/Functions/Summary.php');
require_once('Plugins/-pluginname-/Classes/Model.php');

I find that, this way, only functions that are needed are loaded, and a plugin could almost act stand-alone, as long as it was included from a file giving it the required start-up variables.

So, I was wondering - what is your preferred including/requiring method in your applications? What are the benefits over other methods?

I favour autoloading pretty much everything since it makes adding and removing class files fairly transparent. Secondly there is an implicit cost in using include_once or require_once which autoload does not have. Thirdly, opcode caches like APC have “issues” with the *_once functions.

The most performant approach is using plain include/require but that has it’s obvious drawbacks too.

For me, it’s [fphp]spl_autoload[/fphp] all the way. For one, it’s stackable, so I can have individual components with their own Autoload implementation and as long as they play nice (failing early with a request for non-component object) I can swip-swap 'em about as much as I like.

In addition to this, I find it’s easier to manage the application or autoloading of objects when I have a central place to control it.

For instance, given this, in my bootstrap…

class Application_Autoload
{
    static public function Register(){
        return spl_autoload_register(
            array(
                'Application_Autoload',
                'Load'
            )
        );
    }
    
    static public function Load($objectName){
        #validate, require_once
    }
}

Application_Autoload::Register();

I can quite easily add behaviour to how the objects are supplied in the Application_Autoload::Load method, maybe store a map of where the required files are stored or filter out certain requests.

I find myself just doing a require_once for all classes I need. I see no need to do an include if you NEED that particular function/method. If you go with “well at least some of the page can load” then what’s the point in showing a broken page for?

I honestly don’t see the need for an autoloader method. What’s the difference between using require_once and autoloading? When you initiate an object, it’s gonna be required/included for you anyway.


class foo {
  public function __autoload($class_name) {
    require_once $class_name . '.php';
  }

  //Or
  public function __autoload(array $classNames) {
    foreach($classNames as $class)
      require_once $class . '.php';
  }
}

//When you can just do this:
require_once 'class.b.php';

class c extends b {

}

//Or
require_once 'functions.php';

class c {

}

Both locations (either at the top or in _autoload) provide a nice location to store all the external files that are needed. The only reason to actually use autoloader if it had some type of performance increase. And in that, case, how much more of a boost would it really be? I would imagine that it would be marginal.

Something did catch my attention though, and that’s Anthony’s way with spl_autoload. It seems to provide that little extra reason to go with it then just plain autoload.

I use autoloading, I don’t really like having to use include or require anywhere in my code unless I must. I mostly use indexing cause I use strange naming conventions and structuring.


<?php namespace Markdown;

/**
 * Attemps to assign a global "__autoload" function to spl_autoload stack. Using
 * spl_autoload_register overrides any global "__autoload" function.
 *
 * Builds an index from the respected "__load.php" files in each component.
 */
function __load ()
{
    // No need to re-run the function if its already in.
    if ( in_array( 'Markdown\\\\{closure}', (array)spl_autoload_functions() ) )
        return;

    if ( function_exists( '\\\\__autoload' ) )
      spl_autoload_register( '\\\\__autoload' );

    $index = array(
        'config' => '/config.php',
        'parser' => '/parser.php'
        // class => file ...etc
    );

    // Not required in this project
    //foreach ( glob( __DIR__ . '/[a-z]*/__load.php' ) as $load )
        //$index = array_merge( $index, ( include $load ) );

    spl_autoload_register( function ( $class ) use ( $index ) {
        if ( strpos( $class, 'Markdown\\\\' ) === 0 ) {
            $class = strtolower( str_replace( 'Markdown\\\\', '', $class ) );

            if ( isset( $index[ $class ] ) )
              include __DIR__ . $index[ $class ];
        }
    } );
}

__load();

I’ve been using an indirect auto loader for my personal work based on how you would import packages or classes in Java.


$this->app->getInstance('App.Resource.Template');

The call would import the class file and return an instance of the class Template.

Another way it could be done w/o the indirect auto load.


$this->app->import('App.Resource.Template');
$template = new Template();

I have a handler class which has methods to load models, controllers and views. This provides my core application, then I can extend each element on an instance by instance basis.


	function loadModel($classname)
	{
		$this->classname = $classname;
		$this->loadclassname = strtolower($classname) . '.class.php';
		
		// check for core class (should always exist)
		if (file_exists(CORE_PATH . 'model/' . $this->loadclassname) and !class_exists($this->classname)) 
		{
			require CORE_PATH . 'model/' . $this->loadclassname;
		} else {
			$this->logError(SITE_NAME, CORE_PATH . 'model/' . $this->loadclassname . ' not found'); 
		}
		
		// check for an extended version
		$this->loadclassname = strtolower($classname) . 'Extended.class.php';
		if (file_exists(CUSTOM_PATH . 'model/' . $this->loadclassname)) 
		{
			$this->classname = $this->classname . 'Extended';
			require CUSTOM_PATH . 'model/' . $this->loadclassname;
		}
	}
        // similar methods for view and controller

I start at the controller level and load in required Models and Views.


$this->loadModel('Page'); 
$page = new $this->classname('PUBLIC'); 
$this->loadView('login.php');

never have to think about document paths, never have to write include/require… pretty simple and always reusable - at least for my applications.

<snip to new thread>

@AnthonySterling:

I’m also interested in hearing more about how you implement the spl_autoload and how it’s “stackable”

Anthony is refering to the fact that you can add multiple autoload functions to a stack by using “spl_autoload_register” this is handy if you are using libraries from different vendors with different schemes.

I used it in my own implementation: http://www.sitepoint.com/forums/showpost.php?p=4556776&postcount=5


    spl_autoload_register( function ( $class ) use ( $index ) {
        if ( strpos( $class, 'Markdown\\\\' ) === 0 ) {
            $class = strtolower( str_replace( 'Markdown\\\\', '', $class ) );
 
            if ( isset( $index[ $class ] ) )
              include __DIR__ . $index[ $class ];
        }
    } );

Autoload has its cost too and in most cases it’s much greater than require_once - invoking a function, usually processing some logic in it and then require. Simple require_once is much faster in comparison. But I favour autoload for its convenience. There were discussions about how slow require_once is but after I did my own benchmarks I found the cost to be so small that not worth thinking about at all - at least less than invoking a simple function.

I haven’t used APC but have worked on hosts with eAccelerator and I didn’t notice any issues with require_once.

One thing I’ve done before, is iterating a directory structure (such as /library) and ‘requiring’ all files with a .php extensions. It’s a lazy way of loading all library files. The downside of course is that not all of those included files will be used. In fact it’s likely the majority won’t, so you incur a performance penalty as a result of having to load and parse files you won’t use in that request. For that reason, spl_autoload is preferable.