Login   Register  
PHP Classes
elePHPant
Icontem

File: classload.inc.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Stephan Beal  >  PHPClassLoader  >  classload.inc.php  >  Download  
File: classload.inc.php
Role: ???
Content type: text/plain
Description: PHPClassLoader and ext_include()
Class: PHPClassLoader
Author: By
Last change:
Date: 2001-08-16 12:04
Size: 7,453 bytes
 

Contents

Class file image Download
<?
/************<?
/********************************************************************************
  This is a basic classloader for PHP, designed to give the end user the ability 
to use an include_path-like feature without having access to the include_path 
variable (i.e., for users who don't have admin access to their PHP setup, or who 
don't want to fiddle with it). It uses a Java-like mechanism, substituting 
$PHP_CLASSPATH in place of Java's CLASSPATH.

Note that files containing classes loaded via this tool MUST be named like this:
	Classname.$CLASSLOADER_CLASS_SUFFIX

$CLASSLOADER_CLASS_SUFFIX defaults to ".class.php" but can be reset before this 
file is include()d. If you need a special suffix just for certain files, 
you can create your own classloader

$EXT_INCLUDE_FILE_SUFFIX defaults to ".inc.php" but can be reset at any time before
ext_include() is called. .inc.php files are intended to be include files which
do not contain classes and may or may not create output when include()ed.


License: public domain. do as you will, and that shall be the whole of the law.
Author: stephan@wanderinghorse.net 	http://stephan.rootonfire.org
$Revision: 1.12 $


Sample usages:

	// set up the classloading system:
    $PHP_CLASSPATH = ".:test"; # defaults to HTTP_ENV_VARS[CLASSPATH] (Java's classpath)
	// OPTIONAL: $CLASSLOADER_CLASS_SUFFIX = ".inc.php";

	include( "classload.inc.php" );

	// load MyClass:
	$foo = classload( "test/MyClass" );
    if( $foo == 0 ) die( "fuck!" );
    $foo->foo();

	// try loading the same class using a different name, just to see if we get a dual-include error (we won't)
	$foo = classload( "MyClass" );
    $foo->foo();

	// just to be fancy:
	$class = "MyClass";
	$foo = classload( $class );
    $foo->foo();


	// try ext_include()
    echo (ext_include( "MyFoo.class.php" ) ? "got MyFoo.class.php" : "damn")."<br>";
	$foo = new MyFoo();
	$foo->foo();

	// see how it works:
	show_classload_source();


 
********************************************************************************/

######################################################################
# some global vars

  if( ! isset( $PHP_CLASSPATH ) ) {
	if( isset( $HTTP_ENV_VARS[CLASSPATH] ) ) $PHP_CLASSPATH = $HTTP_ENV_VARS[CLASSPATH];
	else $PHP_CLASSPATH = ".";
  }
  if( ! isset( $CLASSLOADER_CLASS_SUFFIX ) ) $CLASSLOADER_CLASS_SUFFIX = ".class.php";
  if( ! isset( $EXT_INCLUDE_FILE_SUFFIX ) ) $EXT_INCLUDE_FILE_SUFFIX = ".inc.php";


######################################################################
# classload()
# loads the given class and returns an instantiated copy. Returns 0
# on error. For some reason returning 'false' does not work correctly:
# conditionals based on that are invariably incorrectly interpretted.
# If $dieonerror is true, then this function will exit() if there's
# the slightest hint of a problem.

  function classload( $class, $dieonerror = true ) {
	global $DefaultClassLoader;
	$ret = $DefaultClassLoader->load( $class, $dieonerror );
	$gotit =  (strcasecmp( get_class( $ret ), $DefaultClassLoader->clean_classname($class) ) == 0);
	if( $gotit == 0 && $dieonerror ) {
	    echo "fatal classloader error: ".$DefaultClassLoader->error();
	    exit();
	}
    if( $gotit == 0  ) {
	  #echo "classload( $class ): ".$DefaultClassLoader->error();
	  return 0;
	}
	return $ret;
  }

######################################################################
# classload_error()
# returns the last error recorded by the classloader, or an empty string

  function classload_error( $exit = false ) {
	global $DefaultClassLoader;
	if( $exit ) {
	    echo $DefaultClassLoader->error();
	    exit;
	}
	return $DefaultClassLoader->error();
  }


######################################################################
# ext_include()
# a wrapper around include() which uses heuristics similar to classload(),
# except that it does not instantiate anything and does not append
# any suffix to the filename. Returns false on error, else true.
#
    static $ext_include_cache = array();
	function ext_include( $file, $dieonerror = true ) {
		global $DefaultClassLoader, $EXT_INCLUDE_FILE_SUFFIX, $ext_include_cache;
		$paths = split( ":", $DefaultClassLoader->$searchpath );
		if( ! ereg( "\.", $file ) ) $file = $file.$EXT_INCLUDE_FILE_SUFFIX;
		while( list( $k, $d ) = each( $paths ) ) {
		  $f = $d."/$file";
		  if( $ext_include_cache[$f] ) return true; # don't allow multiple inclusion
		  #echo "checking [$f]<br>";				
		  if( ! file_exists( $f ) ) continue;
		  $ext_include_cache[$f] =  include( $f );
		  return $ext_include_cache[$f];
	  }
	  if( $dieonerror ) die( "Couldn't ext_include( '$file' ) from any paths in [".$DefaultClassLoader->searchpath."]!" );
	  return false;
	}

################################################################################
# show_classload_source()
# eye candy.
  function show_classload_source() {
		   show_source( __FILE__ );
  }

################################################################################
#  class PHPClassLoader:
# This can be used directly, but it is not as convenient to do so (because
# you'll probably need to GLOBAL it). A static copy, $DefaultClassLoader, is instantiated
# when this file is include()d, and can be used. It is preferred to use the
# function classload(), however, which does some additional error checking.
#
class PHPClassLoader {

  var $searchpath;
  var $suffix = ".class.php";
  var $error = "";

  function PHPClassLoader( $spath = false, $class_suffix = false ) {
	global $PHP_CLASSPATH;
	if( $spath ) $this->$searchpath = $spath;
	if( $class_suffix ) $this->suffix = $class_suffix;
	if( ! $this->searchpath ) $this->searchpath = $PHP_CLASSPATH;
	#echo "instaniated PHPClassLoader: suffix=[".$this->suffix."] searchpath=[".$this->searchpath."]<br>";
  }

  ########################################
  # strips the path part of a class' name, returning just the class name.
  # i.e.: de/einsurance/mypackage/Foo becomes Foo.
  function clean_classname( $class ) {
	return preg_replace( "/.*\/(\w+)$/", "\\1", $class );
  }

  ########################################
  # Loads the given class, or returns 0.
  #
  function load( $class ) {
	$cl = $this->clean_classname( $class );
	if( class_exists( $cl ) ) return new $cl();
	$this->error = "";
	#echo $this->searchpath."<br>";
	$paths = split( ":", $this->searchpath );
	while( list( $k, $d ) = each( $paths ) ) {
	  $f = $d."/$class".$this->suffix;
	  #echo "checking [$f]<br>";
	  if( ! file_exists( $f ) ) continue;
	  include( $f );
	  if( ! class_exists( $cl ) ) {
	    $this->error = "File [$f] does not contain class [$cl]!";
		return 0;
	  }
	  return new $cl();
	}
	$this->error = "class [$cl]: filename [$class".$this->suffix."] not found in path: [".$this->searchpath."]";
	return 0;
  }  // end PHPClassLoader


	/**
	  Returns the last recorded error.
	*/
	function error() {
	  return $this->error ? "PHPClassLoader: ".$this->error : "";
	}
} // end class PHPClassLoader


######################################################################
# set up some shared vars:
static $DefaultClassLoader;
if( ! isset( $DefaultClassLoader ) ) 
	$DefaultClassLoader = new PHPClassLoader( $PHP_CLASSPATH, $CLASSLOADER_CLASS_SUFFIX );

?>