I have an abstract class and I want to create a derived class and load it with autoload function. What are the rules regarding the location of the abstract class as opposed to the derived class(es)? Can I have the abstract class in a top directory and then a derived class in a directory below that. For example the abstract class in /classes/ and the derived class in /classes/users/.
I am trying to use an autoload function that is
function __autoload($class) {
$strrep = str_replace('_', '/', $class);
require_once($_SERVER['DOCUMENT_ROOT'] . '/classes/' . $strrep . '.php');
}
The abstract class is called /classes/Pages.php and the derived class is called /classes/Pages/MainPage.php. I get an error that says it can’t find it.
The exact errors are
Fatal error: Class 'Pages_MainPage' not found in vhosts\\localmach\\index.php on line 23
which is the calling directory.
The calling code is $main2 = new Pages_MainPage;
Is it possible to do it this way?
I suppose in one sense if I understood everything I just read I never would have asked the question in the first place. 
From what I can understand you are supposed to pass the autoload function a fully qualified path name like c:\vhosts\appname\classes\subdir1\clsName, or like classes_subdir1_clsName, or like /classes/subdir1/slcName but that doesn’t work. And how do I qualify the abstract class? Since the only reference to it is by it’s name in the derived class but that doesn’t give any indication of directory hierarchies.
I guess what I am asking is can you do at least a little interpretation on this. It sounds to me like the autoload function is supposed to handle this already if you pass it the information n the correct format, I’m just not sure what that is. No place in any of the reading does it give an example of what the call looks like. Thanks
Sure, it’s possible.
Take a look as PSR-0, I’d encourage everyone to read it at least once.
<?php
/**
* SplClassLoader implementation that implements the technical interoperability
* standards for PHP 5.3 namespaces and class names.
*
* http://groups.google.com/group/php-standards/web/final-proposal
*
* // Example which loads classes for the Doctrine Common package in the
* // Doctrine\\Common namespace.
* $classLoader = new SplClassLoader('Doctrine\\Common', '/path/to/doctrine');
* $classLoader->register();
*
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Roman S. Borschel <roman@code-factory.org>
* @author Matthew Weier O'Phinney <matthew@zend.com>
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
* @author Fabien Potencier <fabien.potencier@symfony-project.org>
*/
class SplClassLoader
{
private $_fileExtension = '.php';
private $_namespace;
private $_includePath;
private $_namespaceSeparator = '\\\\';
/**
* Creates a new <tt>SplClassLoader</tt> that loads classes of the
* specified namespace.
*
* @param string $ns The namespace to use.
*/
public function __construct($ns = null, $includePath = null)
{
$this->_namespace = $ns;
$this->_includePath = $includePath;
}
/**
* Sets the namespace separator used by classes in the namespace of this class loader.
*
* @param string $sep The separator to use.
*/
public function setNamespaceSeparator($sep)
{
$this->_namespaceSeparator = $sep;
}
/**
* Gets the namespace seperator used by classes in the namespace of this class loader.
*
* @return void
*/
public function getNamespaceSeparator()
{
return $this->_namespaceSeparator;
}
/**
* Sets the base include path for all class files in the namespace of this class loader.
*
* @param string $includePath
*/
public function setIncludePath($includePath)
{
$this->_includePath = $includePath;
}
/**
* Gets the base include path for all class files in the namespace of this class loader.
*
* @return string $includePath
*/
public function getIncludePath()
{
return $this->_includePath;
}
/**
* Sets the file extension of class files in the namespace of this class loader.
*
* @param string $fileExtension
*/
public function setFileExtension($fileExtension)
{
$this->_fileExtension = $fileExtension;
}
/**
* Gets the file extension of class files in the namespace of this class loader.
*
* @return string $fileExtension
*/
public function getFileExtension()
{
return $this->_fileExtension;
}
/**
* Installs this class loader on the SPL autoload stack.
*/
public function register()
{
spl_autoload_register(array($this, 'loadClass'));
}
/**
* Uninstalls this class loader from the SPL autoloader stack.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $className The name of the class to load.
* @return void
*/
public function loadClass($className)
{
if (null === $this->_namespace || $this->_namespace.$this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace.$this->_namespaceSeparator))) {
$fileName = '';
$namespace = '';
if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator))) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension;
require ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName;
}
}
}
Okay, here’s a slightly more simplistic implementation of PHP’s built-in auto-loading features.
Consider the following file-system layout:-
index.php
lib/Public/Transport.php
lib/Public/Transport/Bus.php
index.php
<?php
error_reporting(-1);
ini_set('display_errors', true);
function __autoload($object){
$source = 'lib/' . str_replace('_', DIRECTORY_SEPARATOR, $object) . '.php';
require_once $source;
}
$transport = new Public_Transport_Bus;
echo $transport->display(), PHP_EOL;
Transport.php
<?php
abstract class Public_Transport
{
public function display(){
return sprintf("I'll be using the %s to get to work today.", $this->getName());
}
abstract protected function getName();
}
Bus.php
<?php
class Public_Transport_Bus extends Public_Transport
{
protected function getName(){
return 'Bus';
}
}
The __autoload function is automatically called when an object (class/interface) is needed and not already in scope. So, once we ask for Public_Transport_Bus, it finds Public_Transport at the same time because it needs it.
Thanks so much. I swear I tried that exact thing but I will get on it again first thing this morning and let you know how I make out. I really appreciate the help.
Thanks so much. That did it. And again I swear I tried this but was doing so much swearing at that time that it doesn’t surprise me I missed it. 
Big relief and hopeful it will be a day of no frustration.
cheers!