tags:

views:

162

answers:

3

I am using Kohana and just found this piece of code in their autoloading method

  // Class extension to be evaluated
  $extension = 'class '.$class.' extends '.$class.'_Core { }';

  // Start class analysis
  $core = new ReflectionClass($class.'_Core');

  if ($core->isAbstract())
  {
   // Make the extension abstract
   $extension = 'abstract '.$extension;
  }

  // Transparent class extensions are handled using eval. This is
  // a disgusting hack, but it gets the job done.
  eval($extension);

basically what it does is when I am referring to a class that doesn't exist (through object instantiation, calling class_exists() etc.), Kohana will create a class (eg. Foo) that extends a library class that follows certain naming convention (eg. Foo_Core). just being curious, is there any way to do something similar but without the use of eval?

A: 

I think you're stuck with eval() for that.

It's marked as a "disgusting hack" so that makes it OK :)

I'd be interested to know what you do with such an empty class...

Greg
A: 

If you were wanting to be able to cache your dynamically created classes, you could write out to a file and require it instead. This could be considered equally hack-ish, but it is an option. For classes that are created once and used often, it might be a good solution. For classes that need to be dynamic every time, sticking with eval is probably the best solution.

$proxyClassOnDisk = '/path/to/proxyCodeCache/' . $clazz .'.cachedProxyClass';
if ( ! file_exists($proxyClassOnDisk) ) {
    // Generate the proxy and put it into the proxy class on disk.
    file_put_contents($proxyClassOnDisk, $this->generateProxy($object));
}
require_once($proxyClassOnDisk);

In this example, the idea is that you are creating dynamic proxies for the class of $object. $this->generateProxy($object) will return the string that looks more or less like what $extension looks like in the original question.

This is by no means a complete implementation, just some pseudo code to show what I'm describing.

Beau Simensen
+1  A: 

If you are looking to create a dynamic class then eval() is the goto function (pun intended.) However kind of related, I've found that you can put a class declaration within an if-then statement. So you can do the following:

if(true)
{
    class foo
    {
       // methods
    }
}

I use this to check to see if dynamically created classes (from a configuration file) are current... if so then load the class, otherwise... regenerate the class, and load the new one. So if you're looking to create dynamic classes for similar reasons this might be a solution.

null