views:

28

answers:

2

Say I have a file Foo.php:

<?php
interface ICommand
{
     function doSomething();
}

class Foo implements ICommand
{
    public function doSomething()
    {
        return "I'm Foo output";
    }
}

?>

If I want to create a class of type Foo I could use:

require_once("path/to/Foo.php") ;
$bar = new Foo(); 

But say that I've created a Chain of Command Pattern and I have a configuration file that registers all the possible classes and creates an instance of these classes based on strings that are present in the configuration file.

register("Foo", "path/to/Foo.php");

function register($className, $classPath)
{
    require_once($classPath); //Error if the file isn't included, but lets 
                              //assume that the file "Foo.php" exists.
    $classInstance = new $className; //What happens here if the class Foo isn't 
                                     //defined in the file "Foo.php"? 

    $classInstance->doSomething(); //And what happens here if this code is executed at
                                   //all?
    //Etc...
}

How do I make sure that these classes are actually where the configuration file says they are? And what happens if a class isn't there (but the file is), will it create an instance of a dynamically generated class, that has no further description?

+1  A: 

If you try to instantiate a class that is not defined, e.g.

$o = new IsNotDefined();

the autoloader is invoked and the name of the class is passed as the parameter. If the registered autoloader provides an implementation of the class the script continues "normally". If no implementation of the class can be provided php stops with Fatal error: Class 'IsNotDefined' not found.

You might also be interested in

VolkerK
Thanks for the answer! I've read the __autoloader documentation and what you say is correct for versions below 5.3 (which, naturally, I'm working with (i.e. 5.2) so no exceptions for me ;)) Unfortunately I have default behavior at my disposal so a fatal error is a no-go.
Timo
+1  A: 

You can use class_exists to check if a class has been defined.

If you are calling a class dynamically and also calling a method on that class from within the same function, you may also wish to call that method dynamically (unless all of your classes have the exact same method. If that is the case, you can also use method_exists

Finally, you can also use file_exists to ensure the file can be included:

register("Foo", "path/to/Foo.php", "bar", array('arg1', 'arg2'));

function register($className, $classPath, $methodName, $args)
{
    if(!file_exists($classPath)) return false;

    require_once($classPath);

    if(!class_exists($className)) return false;

    $classInstance = new $className;

    if(!method_exists($classInstance, $methodName)) return false;

    $classInstance->$methodName($args);
}
Rupert
As a matter of fact, my classes do all have the same method (they all implement the interface I describe at the beginning of my question) But never-the-less it's a good idea to actually make this check, since it is possible to add new implementations later on.
Timo