2

I want to include an external file as a class body, something like this:

//$key is alphanumeric
$className='_Module_'.$key;
if(!class_exists($className))
{
    eval(' class '.$className.' extends ModuleContext');
    {
        ...include the file here...
    }
}
eval('$instance=new '.$className.'();');

This does what I want:

//$key is alphanumeric
$className='_Module_'.$key;
if(!class_exists($className))
{
    //There's got to be a better way to do this
    $contents=rtrim(ltrim(trim(file_get_contents($fileName.'.php',true)),'<?php'),'?>');
    //All on one line to preserve line numbering for errors
    eval(' class '.$className.' extends ModuleContext{ '.$contents.' }');
}
eval('$instance=new '.$className.'();');

I don't like using eval to include the whole file because it generates confusing error messages:

PHP Fatal error:  Call to undefined function doFoo() in test/test.php(57) : eval()'d code on line 7

and I've read in other posts that eval()'d code doesn't take advantage of php accelerators. Also, it requres some trimming to remove the '<?php' and '?>' tags, since they don't work so well inside a class definition.

The included file needs to be 'user friendly' to someone who is familiar with PHP, but not object oriented programming - it will have a few pre-defined functions to be filled in by the module implementer.

Is there a way to do this that doesn't use eval for the include?

Jon Hulka
  • 1,259
  • 10
  • 15
  • @user492983 - First, you shouldn't veal code (it's risky and will be hard to read later). Second, why would you want to dynamically create classes, that's not how OOP was meant to work. Third, there's another question where the person wanted to extends a "variable" class: [http://stackoverflow.com/questions/304509/variable-variable-class-extensions-in-php-is-it-possible](http://stackoverflow.com/questions/304509/variable-variable-class-extensions-in-php-is-it-possible) – Francois Deschenes Jun 24 '11 at 04:56
  • But the question is why would you want to dynamically create classes? I'm not sure that this is what OOP is all about. – Francois Deschenes Jun 24 '11 at 19:59
  • I agree on the eval point. That's why I was looking for another solution. Apparently there is no other way to load the class body from a second file, so I've had the project requirements changed to allow the whole class in one file (which is my preference anyway). The classes aren't dynamically created, they are dynamically loaded. In this case, the classes to be loaded aren't known until run time. – Jon Hulka Jun 24 '11 at 20:13
  • @Jon - In that case `$unknown = new {$class};` but that doesn't allow a class to dynamically extend another one. Dynamic means at runtime which means that you're ultimately creating a new class if you extend at runtime. – Francois Deschenes Jun 24 '11 at 22:36
  • I see your point. That is one reason to get away from eval(). If it could have been done with an include, then _conceptually_ it wouldn't have been dynamically extended. In reality, everything in PHP happens dynamically. – Jon Hulka Jun 25 '11 at 03:29
  • Actually on second thought, it would be dynamically extended anyway. So it was a bad idea to start with. Thanks for helping me see the light :D – Jon Hulka Jun 25 '11 at 03:31

2 Answers2

2

If I understand you correctly, ideally you would extend your class rather than trying to evaluate ad-hoc a body for your class:

class ClassA {
  public function greet( $msg ) {
    echo $msg;
  }
}

class ClassB extends ClassA {
  public function wave( $times ) {
    echo sprintf("Waves %s times!", $times);
  }
}

$instance = new ClassB();
$instance->greet("Hello World");
$instance->wave("five");

Note here how I'm able to build off of my class, adding new functionality and properties to the 'body' of it.

Sampson
  • 265,109
  • 74
  • 539
  • 565
  • 1
    @user492983 This is the right answer. Don't dynamically create classes. – cwallenpoole Jun 24 '11 at 04:52
  • Not exactly. There were two problems: 1. load the class body from a second file. I've had the project requirements changed so this isn't necessary any more. 2. Load a class whose name isn't known until run-time. The class to be loaded extends a known class. Is there a way to instantiate this without using eval? What I'm doing now is eval('$instance=new '.$name.'();'); – Jon Hulka Jun 24 '11 at 20:03
  • @user492983 You can split the class declarations up into multiple files if needed. Just be sure to require any class you need to extend. – Sampson Jun 24 '11 at 20:05
  • Yes, but can the class declaration be separated from its body, ie. class x extends y{} - can be loaded from a second file? – Jon Hulka Jun 24 '11 at 20:16
  • @Jon That's a very unorthodox approach, and I cannot think of any reason outside of curiosity to take it. Did you have a good reason to do it this way? – Sampson Jun 24 '11 at 20:19
  • Good reason... no. Project requirement. It was meant to be 'user friendly' for non-OOP programmers, just a file with some function definitions. I've convinced my partner to keep it all together. – Jon Hulka Jun 24 '11 at 20:23
  • I've found the solution to the second question [here](http://stackoverflow.com/questions/3685902/php-dynamic-class-loading). Dynamic loading is do-able without using eval. – Jon Hulka Jun 24 '11 at 20:43
0

May by problem in non using short opening tag?

user710818
  • 23,228
  • 58
  • 149
  • 207